GREEN: io/print_str byte-faithful via @fputs(@stdout) — closes #29
The runtime print path now writes exactly the bytes of its
argument with no implicit trailing newline. `io/print_str` is
byte-faithful; authors who want a newline emit `(do io/print_str
"\n")` themselves.
## Codegen
`crates/ailang-codegen/src/lib.rs`:
- Module preamble: `@puts(ptr)` → `@fputs(ptr, ptr)` plus
`@stdout = external global ptr` (libc's `FILE *stdout`).
- Effect-op lowering for `io/print_str`: emit
`getelementptr +8` then `load ptr, ptr @stdout` then
`call/tail call i32 @fputs(ptr bytes, ptr fp)`. Identical
bytes-pointer GEP, distinct sink.
- The pinned IR-shape test renames from
`print_str_calls_puts_with_bytes_pointer` to
`print_str_calls_fputs_with_bytes_pointer_and_stdout` and now
asserts: bytes-GEP present, stdout-load present, both module-
preamble declarations present, and no `@puts(` call anywhere
in the emitted IR.
## Why this shape, and not the alternatives
- *Rename `io/print_str` to `io/println_str` (issue #29 option 2)*
— kept the auto-newline, just relabelled it. AILang's design
bias is explicit-over-implicit (CLAUDE.md: implicit conversions
cut). Auto-newline is a hidden runtime augmentation; the rename
would have preserved it. Rejected.
- *Append `\n` inside the polymorphic `print` (Show-mediated)
function in `examples/prelude.ail`* — would have been a one-line
fix. Rejected: `print` is the Show-mediated formatter, not a
newline emitter; baking a newline into it would have re-imposed
the same implicit-augmentation problem one layer up, breaking
callers that legitimately want pure-bytes output.
## Fixture / test sweep
30 `.ail` fixtures whose owning tests asserted line-separated
stdout now emit explicit `(do io/print_str "\n")` after each
print. Tests that asserted on multi-line stdout (`show_print_e2e`,
`floats_e2e`, `str_concat_e2e`, `eq_ord_e2e`, several `print_*`
smoke tests) had their fixtures sweetened the same way; assertions
themselves remain the canonical observable output. Fixtures that
never relied on the newline (no test ever read the absence of one)
were left untouched.
## Migrated metadata
- `crates/ailang-core/tests/hash_pin.rs`: the `ordering_match::main`
canonical hash is refreshed (`b65a7f834703ffb4` →
`8ed47b4062ce00f5`). The comment now names both successive
corpus migrations honestly: the per-type-print-retirement (which
moved `(do io/print_int x)` to `(app print x)`) AND this
fputs swap (which wrapped that with `(seq ... (do io/print_str
"\n"))`).
- `design/contracts/str-abi.md`: the consumer-ABI table now lists
`@fputs` as the print sink. A prose paragraph documents the
byte-faithful semantics and references this issue.
- `examples/ordering_match.prose.txt`: regenerated from the
updated `ordering_match.ail`.
- `crates/ail/tests/snapshots/{hello,sum,max3,list,ws_main}.ll`:
IR snapshots regenerated via `UPDATE_SNAPSHOTS=1`.
- Stale `@puts` comments in `runtime/str.c`,
`crates/ail/tests/{e2e,show_print_e2e,print_no_leak_pin}.rs`
replaced with `@fputs`.
## Verification
- `cargo test -p ail --test print_str_no_auto_newline_e2e` — both
RED tests from commit c8ecfa3 now pass.
- `cargo test --workspace` — 90 test groups GREEN, 0 failures.
- `cargo build --workspace` — GREEN.
- No new clippy lints (24 warnings pre-existing in
`crates/ailang-core/src/lib.rs:129`).
- Stats: `bench/orchestrator-stats/2026-05-21-iter-bugfix-print-
str-fputs.json` — 1/1 tasks, 0 re-loops, 0 review loops.
## Empirical evidence cited
Caught in the 2026-05-21 Qwen3-Coder naming-A/B run
(`experiments/2026-05-21-naming-ab/runs/r1/`): every cohort wrote
`(do io/print_str "...\n")` with explicit `\n` and got doubled
newlines, failing the `t3_main_prints` stdout match across all
three cohorts. The empirical LLM-natural form already assumes the
new (post-this-commit) semantics — confirming the
feature-acceptance test in CLAUDE.md.
closes #29
This commit is contained in:
@@ -3,4 +3,4 @@
|
||||
(doc "Iter 24.1: pin that `bool_to_str` participates in RC discipline. Bind the heap-Str result to `s`, consume `s` once in `io/print_str`, let the binder drop at scope close. Under --alloc=rc with AILANG_RC_STATS=1 the atexit summary must report allocs == 1 && frees == 1 && live == 0 — the heap-Str slab allocated by str_alloc inside ailang_bool_to_str rides the same rc_header + ailang_rc_dec path as int_to_str.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let s (app bool_to_str true) (do io/print_str s)))))
|
||||
(body (let s (app bool_to_str true) (seq (do io/print_str s) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter 24.1: stdout-smoke for the false branch of bool_to_str. Stdout must be `false\\n` (puts adds the newline). Companion of bool_to_str_drop_rc.ail.json (which covers the true branch and the RC-stats invariant).")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let s (app bool_to_str false) (do io/print_str s)))))
|
||||
(body (let s (app bool_to_str false) (seq (do io/print_str s) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -60,5 +60,5 @@
|
||||
(term-ctor List Cons 3
|
||||
(term-ctor List Nil))))
|
||||
(seq
|
||||
(app print (app list_length xs))
|
||||
(app print (app sum_list xs)))))))
|
||||
(seq (app print (app list_length xs)) (do io/print_str "\n"))
|
||||
(seq (app print (app sum_list xs)) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -2,31 +2,31 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (match (app compare 1 2)
|
||||
(body (seq (seq (app print (match (app compare 1 2)
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (seq (app print (match (app compare 1 1)
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (seq (app print (match (app compare 1 1)
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (seq (app print (match (app compare 2 1)
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (seq (app print (match (app compare 2 1)
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (seq (app print (match (app compare false true)
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (seq (app print (match (app compare false true)
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (seq (app print (match (app compare false false)
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (seq (app print (match (app compare false false)
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (seq (app print (match (app compare true false)
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (seq (app print (match (app compare true false)
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (seq (app print (match (app compare "a" "b")
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (seq (app print (match (app compare "a" "b")
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (seq (app print (match (app compare "a" "a")
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (seq (app print (match (app compare "a" "a")
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))) (app print (match (app compare "b" "a")
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")) (seq (app print (match (app compare "b" "a")
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))))))))))))))
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")))))))))))))
|
||||
|
||||
+10
-10
@@ -47,13 +47,13 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app eq 5 5))
|
||||
(seq (app print (app eq 5 6))
|
||||
(seq (app print (app eq true false))
|
||||
(seq (app print (app eq true true))
|
||||
(seq (app print (app eq "hi" "hi"))
|
||||
(seq (app print (app eq "hi" "ho"))
|
||||
(seq (app print (app eq (lit-unit) (lit-unit)))
|
||||
(seq (app print (app classify_str "hi"))
|
||||
(seq (app print (app classify_str "ho"))
|
||||
(app print (app classify_str "??"))))))))))))))
|
||||
(seq (seq (app print (app eq 5 5)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app eq 5 6)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app eq true false)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app eq true true)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app eq "hi" "hi")) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app eq "hi" "ho")) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app eq (lit-unit) (lit-unit))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app classify_str "hi")) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app classify_str "ho")) (do io/print_str "\n"))
|
||||
(seq (app print (app classify_str "??")) (do io/print_str "\n"))))))))))))))
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (if (app at_most 3 5) 1 0)) (seq (app print (if (app at_most true false) 1 0)) (app print (if (app at_most "abc" "abd") 1 0)))))))
|
||||
(body (seq (seq (app print (if (app at_most 3 5) 1 0)) (do io/print_str "\n")) (seq (seq (app print (if (app at_most true false) 1 0)) (do io/print_str "\n")) (seq (app print (if (app at_most "abc" "abd") 1 0)) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -21,4 +21,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (if (app eq (term-ctor IntBox MkIntBox 3) (term-ctor IntBox MkIntBox 3)) 1 0)) (app print (if (app eq (term-ctor IntBox MkIntBox 3) (term-ctor IntBox MkIntBox 5)) 1 0))))))
|
||||
(body (seq (seq (app print (if (app eq (term-ctor IntBox MkIntBox 3) (term-ctor IntBox MkIntBox 3)) 1 0)) (do io/print_str "\n")) (seq (app print (if (app eq (term-ctor IntBox MkIntBox 3) (term-ctor IntBox MkIntBox 5)) 1 0)) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (app to_int (app eq 7 7))) (seq (app print (app to_int (app eq 7 8))) (seq (app print (app to_int (app eq true true))) (seq (app print (app to_int (app eq true false))) (seq (app print (app to_int (app eq "hello" "hello"))) (app print (app to_int (app eq "hello" "world")))))))))))
|
||||
(body (seq (seq (app print (app to_int (app eq 7 7))) (do io/print_str "\n")) (seq (seq (app print (app to_int (app eq 7 8))) (do io/print_str "\n")) (seq (seq (app print (app to_int (app eq true true))) (do io/print_str "\n")) (seq (seq (app print (app to_int (app eq true false))) (do io/print_str "\n")) (seq (seq (app print (app to_int (app eq "hello" "hello"))) (do io/print_str "\n")) (seq (app print (app to_int (app eq "hello" "world"))) (do io/print_str "\n"))))))))))
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
(let p1 (term-ctor Point Point 1 2)
|
||||
(let p2 (term-ctor Point Point 1 2)
|
||||
(let p3 (term-ctor Point Point 1 3)
|
||||
(seq (app print (app eq (lit-unit) (lit-unit)))
|
||||
(seq (app print (app eq p1 p2))
|
||||
(app print (app eq p1 p3))))))))))
|
||||
(seq (seq (app print (app eq (lit-unit) (lit-unit))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app eq p1 p2)) (do io/print_str "\n"))
|
||||
(seq (app print (app eq p1 p3)) (do io/print_str "\n"))))))))))
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app peek 0))
|
||||
(seq (app print (app peek 123))
|
||||
(seq (app print (app count 5))
|
||||
(app print (app count 0))))))))
|
||||
(seq (seq (app print (app peek 0)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app peek 123)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app count 5)) (do io/print_str "\n"))
|
||||
(seq (app print (app count 0)) (do io/print_str "\n"))))))))
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app float_eq 1.5 1.5))
|
||||
(seq (app print (app float_lt 1.0 2.0))
|
||||
(app print (app float_eq 1.0 0.0)))))))
|
||||
(seq (seq (app print (app float_eq 1.5 1.5)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app float_lt 1.0 2.0)) (do io/print_str "\n"))
|
||||
(seq (app print (app float_eq 1.0 0.0)) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter hs.4: smoke pin for the float_to_str heap-Str builtin. `do io/print_str(float_to_str(3.5))` builds through the whole pipeline (checker resolves float_to_str:(Float)->Str, codegen lowers to call ptr @ailang_float_to_str(double 3.5), runtime/str.c's ailang_float_to_str snprintfs into a heap-Str slab via libc %g plus a `.0`-fallback for finite whole-valued doubles whose %g output lacks `.`/`e`/`E` (Gitea #7), io/print_str's @puts prints from the bytes pointer at offset 8). The exact rendering of 3.5 is libc-target-dependent; on the dev target's clang+glibc with default C locale it is the three bytes `3.5` (the fallback does not fire because `.` is already present). Single-value smoke; NaN / +Inf / -Inf edge cases are deferred per the hs.4 plan.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (do io/print_str (app float_to_str 3.5)))))
|
||||
(body (seq (do io/print_str (app float_to_str 3.5)) (do io/print_str "\n")))))
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (app + 1.5 2.5)) (seq (app print (app int_to_float 42)) (app print (app neg 1.5)))))))
|
||||
(body (seq (seq (app print (app + 1.5 2.5)) (do io/print_str "\n")) (seq (seq (app print (app int_to_float 42)) (do io/print_str "\n")) (seq (app print (app neg 1.5)) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter eob.1: heap-Str passed to io/print_str twice in sequence. Under the new rule (Term::Do args = Borrow), the second call no longer triggers use-after-consume; the linearity check accepts the program. Under --alloc=rc + AILANG_RC_STATS=1 the slab allocates once and is freed once at scope close (allocs == 1, frees == 1, live == 0).")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let s (app int_to_str 42) (seq (do io/print_str s) (do io/print_str s))))))
|
||||
(body (let s (app int_to_str 42) (seq (seq (do io/print_str s) (do io/print_str "\n")) (seq (do io/print_str s) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter eob.1 / rpe.1: primitive Int passed to the polymorphic `print` helper (Show Int). The rule that Term::Do args are Borrow has no observable RC effect here because Int is unboxed; the test pins that no spurious bookkeeping appears (allocs == 0, frees == 0, live == 0).")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let n 7 (app print n)))))
|
||||
(body (let n 7 (seq (app print n) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter hs.4: pin that `int_to_str` participates in RC discipline. Bind the heap-Str result to `s`, consume `s` once in `io/print_str`, let the binder drop at scope close. Under --alloc=rc with AILANG_RC_STATS=1 the atexit summary must report allocs == frees && live == 0 — the heap-Str slab allocated by str_alloc inside ailang_int_to_str rides the same rc_header + ailang_rc_dec path as any other RC value.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let s (app int_to_str 42) (do io/print_str s)))))
|
||||
(body (let s (app int_to_str 42) (seq (do io/print_str s) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter hs.4: smoke pin for the int_to_str heap-Str builtin. `do io/print_str(int_to_str(42))` builds through the whole pipeline (checker resolves int_to_str:(Int)->Str, codegen lowers to call ptr @ailang_int_to_str(i64 42), runtime/str.c's ailang_int_to_str snprintfs into a heap-Str slab, io/print_str's @puts prints from the bytes pointer at offset 8). Single-value smoke; the spec's broader edge-case sweep (0, -1, i64::MAX, i64::MIN) is deferred to a follow-up tidy iter per the hs.4 plan.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (do io/print_str (app int_to_str 42)))))
|
||||
(body (seq (do io/print_str (app int_to_str 42)) (do io/print_str "\n")))))
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
(params xs)
|
||||
(body (match xs
|
||||
(case (pat-ctor Nil) (lit-unit))
|
||||
(case (pat-ctor Cons h t) (seq (app print h) (app print_list t))))))
|
||||
(case (pat-ctor Cons h t) (seq (seq (app print h) (do io/print_str "\n")) (app print_list t))))))
|
||||
(fn main
|
||||
(doc "Build [1,2,3], double each, print result.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
(lit-unit))
|
||||
(case (pat-ctor Cons h t)
|
||||
(seq
|
||||
(app print h)
|
||||
(seq (app print h) (do io/print_str "\n"))
|
||||
(tail-app print_list t))))))
|
||||
|
||||
(fn main
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app classify 0))
|
||||
(seq (app print (app classify 1))
|
||||
(seq (app print (app classify 17))
|
||||
(seq (app print (app categorize_first (term-ctor IntList Nil)))
|
||||
(seq (app print (app categorize_first (term-ctor IntList Cons 0 (term-ctor IntList Nil))))
|
||||
(app print (app categorize_first (term-ctor IntList Cons 7 (term-ctor IntList Nil))))))))))))
|
||||
(seq (seq (app print (app classify 0)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app classify 1)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app classify 17)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app categorize_first (term-ctor IntList Nil))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app categorize_first (term-ctor IntList Cons 0 (term-ctor IntList Nil)))) (do io/print_str "\n"))
|
||||
(seq (app print (app categorize_first (term-ctor IntList Cons 7 (term-ctor IntList Nil)))) (do io/print_str "\n"))))))))))
|
||||
|
||||
@@ -39,5 +39,5 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app run_with_base 10))
|
||||
(app print (app run_with_base 100))))))
|
||||
(seq (seq (app print (app run_with_base 10)) (do io/print_str "\n"))
|
||||
(seq (app print (app run_with_base 100)) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -30,6 +30,6 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app sum_below 1))
|
||||
(seq (app print (app sum_below 5))
|
||||
(app print (app sum_below 10)))))))
|
||||
(seq (seq (app print (app sum_below 1)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app sum_below 5)) (do io/print_str "\n"))
|
||||
(seq (app print (app sum_below 10)) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
1
|
||||
(app * n (app fact (app - n 1)))))
|
||||
(in
|
||||
(seq (app print (app fact 1))
|
||||
(seq (app print (app fact 3))
|
||||
(app print (app fact 5)))))))))
|
||||
(seq (seq (app print (app fact 1)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app fact 3)) (do io/print_str "\n"))
|
||||
(seq (app print (app fact 5)) (do io/print_str "\n")))))))))
|
||||
|
||||
@@ -43,6 +43,6 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app count_below 0))
|
||||
(seq (app print (app count_below 5))
|
||||
(app print (app count_below 15)))))))
|
||||
(seq (seq (app print (app count_below 0)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app count_below 5)) (do io/print_str "\n"))
|
||||
(seq (app print (app count_below 15)) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -54,6 +54,6 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app count_below (term-ctor Pair MkPair 10 0)))
|
||||
(seq (app print (app count_below (term-ctor Pair MkPair 10 5)))
|
||||
(app print (app count_below (term-ctor Pair MkPair 10 15))))))))
|
||||
(seq (seq (app print (app count_below (term-ctor Pair MkPair 10 0))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app count_below (term-ctor Pair MkPair 10 5))) (do io/print_str "\n"))
|
||||
(seq (app print (app count_below (term-ctor Pair MkPair 10 15))) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
(doc "Print or_else for both arms; expected 7 then 99.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (app or_else (term-ctor Maybe Some 7) 99)) (app print (app or_else (term-ctor Maybe None) 99))))))
|
||||
(body (seq (seq (app print (app or_else (term-ctor Maybe Some 7) 99)) (do io/print_str "\n")) (seq (app print (app or_else (term-ctor Maybe None) 99)) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -48,6 +48,6 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app nested_sum 1))
|
||||
(seq (app print (app nested_sum 3))
|
||||
(app print (app nested_sum 5)))))))
|
||||
(seq (seq (app print (app nested_sum 1)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app nested_sum 3)) (do io/print_str "\n"))
|
||||
(seq (app print (app nested_sum 5)) (do io/print_str "\n")))))))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
(doc "Nullary user function — no params, prints a fixed line.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (do io/print_str "hello")))
|
||||
(body (seq (do io/print_str "hello") (do io/print_str "\n"))))
|
||||
|
||||
(fn main
|
||||
(doc "Calls the nullary `greet` as `(app greet)` — the zero-arg surface form accepted under Gitea #12.")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
(doc "Iter 23.1 fixture: pattern-match on prelude Ordering ctor without explicit prelude import.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (app print (match (term-ctor prelude.Ordering LT)
|
||||
(body (seq (app print (match (term-ctor prelude.Ordering LT)
|
||||
(case (pat-ctor LT) 1)
|
||||
(case (pat-ctor EQ) 2)
|
||||
(case (pat-ctor GT) 3))))))
|
||||
(case (pat-ctor GT) 3))) (do io/print_str "\n")))))
|
||||
|
||||
@@ -7,5 +7,6 @@ fn main() -> Unit with IO {
|
||||
LT => 1,
|
||||
EQ => 2,
|
||||
GT => 3
|
||||
})
|
||||
});
|
||||
do io/print_str("\n")
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (app id 42)) (app print (app id true))))))
|
||||
(body (seq (seq (app print (app id 42)) (do io/print_str "\n")) (seq (app print (app id true)) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -53,5 +53,5 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app apply_n_times 5 0 succ))
|
||||
(app print (app apply_n_times 4 false flip))))))
|
||||
(seq (seq (app print (app apply_n_times 5 0 succ)) (do io/print_str "\n"))
|
||||
(seq (app print (app apply_n_times 4 false flip)) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "RED pin for Gitea #7: a whole-valued Float (here, the literal 2.0) routed through polymorphic `print` (which monomorphises to Show Float.show -> float_to_str -> runtime/str.c::ailang_float_to_str -> libc snprintf %g) must render with a `.0` suffix, matching the surface printer's write_float_lit fallback (crates/ailang-surface/src/print.rs lines 624-637). The desired stdout for this fixture is the three bytes `2.0\\n`. Pre-fix, libc %g strips trailing zeros and renders `2\\n` — Int-shaped output for a Float value — which violates the surface-runtime round-trip-on-lex symmetry the language relies on.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (app print 2.0))))
|
||||
(body (seq (app print 2.0) (do io/print_str "\n")))))
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (seq (seq (app print 42) (app print true)) (app print "hello")) (app print 3.14)))))
|
||||
(body (seq (seq (seq (seq (app print 42) (do io/print_str "\n")) (seq (app print true) (do io/print_str "\n"))) (seq (app print "hello") (do io/print_str "\n"))) (app print 3.14)))))
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (app print (term-ctor Item MkItem 42)))))
|
||||
(body (seq (app print (term-ctor Item MkItem 42)) (do io/print_str "\n")))))
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
(params xs)
|
||||
(body (match xs
|
||||
(case (pat-ctor Nil) (lit-unit))
|
||||
(case (pat-ctor Cons h t) (seq (app print h) (tail-app print_list t))))))
|
||||
(case (pat-ctor Cons h t) (seq (seq (app print h) (do io/print_str "\n")) (tail-app print_list t))))))
|
||||
(fn main
|
||||
(doc "Sort and print [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app std_either.from_right 0 (term-ctor std_either.Either Right 42)))
|
||||
(seq (app print (app std_either.from_right 99 (term-ctor std_either.Either Left 7)))
|
||||
(seq (app print (app std_either.is_left (term-ctor std_either.Either Left 7)))
|
||||
(seq (app print (app std_either.is_right (term-ctor std_either.Either Right 42)))
|
||||
(seq (app print (app std_either.from_right 0
|
||||
(seq (seq (app print (app std_either.from_right 0 (term-ctor std_either.Either Right 42))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_either.from_right 99 (term-ctor std_either.Either Left 7))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_either.is_left (term-ctor std_either.Either Left 7))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_either.is_right (term-ctor std_either.Either Right 42))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_either.from_right 0
|
||||
(app std_either.map_right inc
|
||||
(term-ctor std_either.Either Right 41))))
|
||||
(seq (app print (app std_either.either inc inc
|
||||
(term-ctor std_either.Either Left 5)))
|
||||
(app print (app std_either.either inc inc
|
||||
(term-ctor std_either.Either Right 100))))))))))))
|
||||
(term-ctor std_either.Either Right 41)))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_either.either inc inc
|
||||
(term-ctor std_either.Either Left 5))) (do io/print_str "\n"))
|
||||
(seq (app print (app std_either.either inc inc
|
||||
(term-ctor std_either.Either Right 100))) (do io/print_str "\n")))))))))))
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app std_list.length (app std_either_list.lefts (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil)))))))))
|
||||
(seq (app print (app std_list.length (app std_either_list.rights (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil)))))))))
|
||||
(seq (app print (app std_list.length (app std_pair.fst (app std_either_list.partition_eithers (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil))))))))))
|
||||
(app print (app std_list.length (app std_pair.snd (app std_either_list.partition_eithers (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil))))))))))))))))
|
||||
(seq (seq (app print (app std_list.length (app std_either_list.lefts (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil))))))))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_either_list.rights (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil))))))))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_pair.fst (app std_either_list.partition_eithers (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil)))))))))) (do io/print_str "\n"))
|
||||
(seq (app print (app std_list.length (app std_pair.snd (app std_either_list.partition_eithers (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil)))))))))) (do io/print_str "\n"))))))))
|
||||
|
||||
+11
-11
@@ -48,14 +48,14 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app std_list.length xs))
|
||||
(seq (app print (app std_list.is_empty xs))
|
||||
(seq (app print (app std_list.is_empty (term-ctor std_list.List Nil)))
|
||||
(seq (app print (app std_maybe.from_maybe -1 (app std_list.head xs)))
|
||||
(seq (app print (app std_list.length (app std_maybe.from_maybe xs (app std_list.tail xs))))
|
||||
(seq (app print (app std_list.length (app std_list.append xs xs)))
|
||||
(seq (app print (app std_maybe.from_maybe -1 (app std_list.head (app std_list.reverse xs))))
|
||||
(seq (app print (app std_maybe.from_maybe -1 (app std_list.head (app std_list.map double xs))))
|
||||
(seq (app print (app std_list.length (app std_list.filter is_even xs)))
|
||||
(seq (app print (app std_list.fold_left add 0 xs))
|
||||
(app print (app std_list.fold_right add 0 xs)))))))))))))))
|
||||
(seq (seq (app print (app std_list.length xs)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.is_empty xs)) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.is_empty (term-ctor std_list.List Nil))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_maybe.from_maybe -1 (app std_list.head xs))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_maybe.from_maybe xs (app std_list.tail xs)))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_list.append xs xs))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_maybe.from_maybe -1 (app std_list.head (app std_list.reverse xs)))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_maybe.from_maybe -1 (app std_list.head (app std_list.map double xs)))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_list.filter is_even xs))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.fold_left add 0 xs)) (do io/print_str "\n"))
|
||||
(seq (app print (app std_list.fold_right add 0 xs)) (do io/print_str "\n")))))))))))))))
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app std_list.length (app std_list.take 0 xs)))
|
||||
(seq (app print (app std_list.length (app std_list.take 3 xs)))
|
||||
(seq (app print (app std_list.length (app std_list.take 100 xs)))
|
||||
(seq (app print (app std_list.length (app std_list.drop 0 xs)))
|
||||
(seq (app print (app std_list.length (app std_list.drop 2 xs)))
|
||||
(app print (app std_list.length (app std_list.drop 100 xs)))))))))))
|
||||
(seq (seq (app print (app std_list.length (app std_list.take 0 xs))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_list.take 3 xs))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_list.take 100 xs))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_list.drop 0 xs))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_list.length (app std_list.drop 2 xs))) (do io/print_str "\n"))
|
||||
(seq (app print (app std_list.length (app std_list.drop 100 xs))) (do io/print_str "\n"))))))))))
|
||||
|
||||
@@ -37,5 +37,5 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app std_list.fold_left add 0 (app build 1000)))
|
||||
(app print (app std_list.fold_right add 0 (app build 1000)))))))
|
||||
(seq (seq (app print (app std_list.fold_left add 0 (app build 1000))) (do io/print_str "\n"))
|
||||
(seq (app print (app std_list.fold_right add 0 (app build 1000))) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app std_maybe.from_maybe 99 (term-ctor std_maybe.Maybe Just 7)))
|
||||
(seq (app print (app std_maybe.from_maybe 99 (term-ctor std_maybe.Maybe Nothing)))
|
||||
(seq (app print (app std_maybe.is_some (term-ctor std_maybe.Maybe Just 5)))
|
||||
(seq (app print (app std_maybe.is_none (term-ctor std_maybe.Maybe Nothing)))
|
||||
(app print (app std_maybe.from_maybe 0 (app std_maybe.map_maybe inc (term-ctor std_maybe.Maybe Just 41)))))))))))
|
||||
(seq (seq (app print (app std_maybe.from_maybe 99 (term-ctor std_maybe.Maybe Just 7))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_maybe.from_maybe 99 (term-ctor std_maybe.Maybe Nothing))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_maybe.is_some (term-ctor std_maybe.Maybe Just 5))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_maybe.is_none (term-ctor std_maybe.Maybe Nothing))) (do io/print_str "\n"))
|
||||
(seq (app print (app std_maybe.from_maybe 0 (app std_maybe.map_maybe inc (term-ctor std_maybe.Maybe Just 41)))) (do io/print_str "\n")))))))))
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app std_pair.fst (term-ctor std_pair.Pair MkPair 7 9)))
|
||||
(seq (app print (app std_pair.snd (term-ctor std_pair.Pair MkPair 7 9)))
|
||||
(seq (app print (app std_pair.fst (app std_pair.swap (term-ctor std_pair.Pair MkPair 7 9))))
|
||||
(seq (app print (app std_pair.snd (app std_pair.swap (term-ctor std_pair.Pair MkPair 7 9))))
|
||||
(seq (app print (app std_pair.fst (app std_pair.map_first inc (term-ctor std_pair.Pair MkPair 7 9))))
|
||||
(app print (app std_pair.snd (app std_pair.map_second double (term-ctor std_pair.Pair MkPair 7 9))))))))))))
|
||||
(seq (seq (app print (app std_pair.fst (term-ctor std_pair.Pair MkPair 7 9))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_pair.snd (term-ctor std_pair.Pair MkPair 7 9))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_pair.fst (app std_pair.swap (term-ctor std_pair.Pair MkPair 7 9)))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_pair.snd (app std_pair.swap (term-ctor std_pair.Pair MkPair 7 9)))) (do io/print_str "\n"))
|
||||
(seq (seq (app print (app std_pair.fst (app std_pair.map_first inc (term-ctor std_pair.Pair MkPair 7 9)))) (do io/print_str "\n"))
|
||||
(seq (app print (app std_pair.snd (app std_pair.map_second double (term-ctor std_pair.Pair MkPair 7 9)))) (do io/print_str "\n"))))))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter 24.1: cross-realisation invariant for str_clone. Clones a heap-Str (produced by int_to_str 42) AND a static-Str (literal `abc`); both clones produce fresh heap-Str slabs that print their input bytes. Pins the uniform-consumer-ABI claim — str_clone only reads the len-field at offset 0 plus the bytes plus the NUL; it never consults the (absent for static-Str) rc_header. RC stats under --alloc=rc: allocs == 3 (int_to_str output + two str_clone outputs), frees == 3, live == 0.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let src_heap (app int_to_str 42) (let c1 (app str_clone src_heap) (let c2 (app str_clone "abc") (let _a (do io/print_str c1) (do io/print_str c2))))))))
|
||||
(body (let src_heap (app int_to_str 42) (let c1 (app str_clone src_heap) (let c2 (app str_clone "abc") (let _a (seq (do io/print_str c1) (do io/print_str "\n")) (seq (do io/print_str c2) (do io/print_str "\n")))))))))
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
(doc "Iter 24.1: pin that `str_clone` participates in RC discipline AND emits correct bytes. Input is a static-Str literal; the clone produces a fresh heap-Str slab whose payload is byte-equal to the input. RC stats under --alloc=rc with AILANG_RC_STATS=1: allocs == 1 (the clone), frees == 1 (let-binder drop at scope close), live == 0.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let s (app str_clone "hello") (do io/print_str s)))))
|
||||
(body (let s (app str_clone "hello") (seq (do io/print_str s) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (let b (term-ctor Boxed Box (app int_to_str 42)) (match b
|
||||
(case (pat-ctor Box s) (do io/print_str s)))))))
|
||||
(case (pat-ctor Box s) (seq (do io/print_str s) (do io/print_str "\n"))))))))
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
(fn main
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body (seq (app print (app r 0)) (app print (app r true))))))
|
||||
(body (seq (seq (app print (app r 0)) (do io/print_str "\n")) (seq (app print (app r true)) (do io/print_str "\n"))))))
|
||||
|
||||
@@ -31,5 +31,5 @@
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (app print (app safe_div 8 2))
|
||||
(app print (app safe_div 15 3))))))
|
||||
(seq (seq (app print (app safe_div 8 2)) (do io/print_str "\n"))
|
||||
(seq (app print (app safe_div 15 3)) (do io/print_str "\n"))))))
|
||||
|
||||
Reference in New Issue
Block a user