feat(lang): eliminate the Implicit ownership default — totality + the drop-soundness it demasks (#55)

Deletes `ParamMode::Implicit`. `ParamMode` is now `{Own, Borrow}`:
every fn-type slot on every signature carries an explicit `own` or
`borrow`, no defaulted position survives anywhere (model 0008 §2,
spec 0062). The parser rejects a bare fn-type slot; `borrow-return`
and `borrow-over-value` reject at the signature; the corpus is
migrated to minimal-ownership modes (consumed ⇒ own, read-only-heap
⇒ borrow, value ⇒ trivial-own). The documented `Implicit`-ret-mode
leak is fixed: an owned heap return now drops exactly once (live=0,
acceptance criterion 5).

This was the easy half. Removing the default ACTIVATED a family of
drop paths that `Implicit` had silently skipped — the pre-cutover
language was leaking (and in places mis-dropping) here rather than
crashing, because an Implicit scrutinee turned the drop off. Making
the modes explicit (Own) turned those paths on and exposed two
latent-bug clusters, all fixed RED-first as part of this cutover:

Drop-soundness family (four legs):
  A. lit-sub-pattern double-free — the desugar re-matched the same
     owned scrutinee in the lit fall-through; fixed by grouping
     consecutive same-ctor arms into one match (bind fields once),
     in ailang-core desugar.
  B. Cons-husk leak on non-tail arm bodies — the lit-sub-pattern
     desugar rebound the owned scrutinee via `Let $mp = xs`, which
     bumped consume_count and suppressed the existing fn-return
     partial_drop. Fixed by not rebinding a bare-Var scrutinee
     (one husk-freeing mechanism, not two).
  C. polymorphic `drop_<T>` rc_dec'd monomorphised value fields —
     the per-ADT drop fn was emitted once from the polymorphic
     TypeDef, defaulting type-var fields to ptr and rc_dec'ing
     inline Ints (segfault). Fixed with per-monomorph drop
     functions (new ailang-codegen::dropmono): the drop set is
     collected from the lowered MIR, value-type fields are skipped,
     heap fields still freed once; monomorphic-concrete ADTs keep
     their byte-identical un-suffixed drop symbol.
  D. static Str literal passed to an `(own Str)` param — the
     literal lowers to a header-less rodata constant; the callee's
     now-active rc_dec read its length field as a refcount and
     freed a static address (segfault). Fixed with the missing
     fourth StrRep::Static→Heap promotion in lower_to_mir's App arm,
     gated on Own mode (borrow args stay static, no regression).

over-strict-mode lint over-fired: it suggested `(borrow V)` for
value-typed params (which `borrow-over-value` rejects — own is the
only legal mode there) and fired on `(intrinsic)` bodies (whose
consumption the linearity walk cannot observe). Tightened to skip
both; contract 0008 updated to the narrowed firing scope.

Irreversible step — canonical-form hash reset (model 0008 §6,
acceptance criterion 6). Every signature now carries explicit modes,
so the hashable canonical JSON changed for every module. RATIFY:
the corpus-wide hash-pin reset (hash_pin, prelude_module_hash_pin,
mono_hash_stability, eq_ord_e2e, embed_export_hash_stable, the
ct4/iter*/loop_recur schema-extension pins) and the list ir_snapshot
golden were regenerated once, deliberately, as the intended one-time
consequence of removing the mode elision from the canonical form —
not a regression. Each regenerated hash verified deterministic across
two runs.

Also fixes a pre-existing latent failure surfaced by the verification
gate, unrelated to this cutover: the `every_contract_names_a_resolvable_
ratifying_test` resolver (design_index_pin) could not resolve the
" + " dual-link ratifying-test form (`uniqueness.rs + linearity.rs`)
that the #57 audit-close (dfdc65f) introduced — it shipped red on that
commit. Resolver taught the dual-link form, mirroring its sibling.

Verification: cargo test --workspace = 731 passed, 0 failed (twice,
stable); e2e 102 passed, no binary exits non-zero (corpus crash-free);
grep-clean for Implicit/fn_implicit/mode_eq across crates; every drop
fix confirmed via emitted IR + AILANG_RC_STATS balance on the head==K,
head!=K, and Nil paths. Three BLOCKEDs en route (the unsound first
husk-dec attempt, the over-strict derivation premise, the leg-B fix
direction) were each treated as a real design/spec gap and rediagnosed,
not patched over.

Supersedes #54 (return-position-only leak patch). Precondition #57
(linearity hardening) was already met. Spec docs/specs/0062, plan
docs/plans/0121.

closes #55
This commit is contained in:
2026-06-02 00:03:46 +02:00
parent 05c3c018de
commit 76b21c00eb
342 changed files with 3196 additions and 1503 deletions
+2 -2
View File
@@ -9,8 +9,8 @@
(export "ema_step")
(type
(fn-type
(params (con Int) (con Int))
(ret (con Int))))
(params (own (con Int)) (own (con Int)))
(ret (own (con Int)))))
(params state sample)
(body
(app + state
@@ -9,8 +9,8 @@
(export "leaky_step")
(type
(fn-type
(params (con Float) (con Float))
(ret (con Float))))
(params (own (con Float)) (own (con Float)))
(ret (own (con Float)))))
(params state sample)
(body
(app + (app * state 0.5) sample))))
@@ -16,7 +16,7 @@
(type
(fn-type
(params (own (con IntList)))
(ret (con Int))))
(ret (own (con Int)))))
(params xs)
(body
(match xs
@@ -13,8 +13,8 @@
(export "tick")
(type
(fn-type
(params (con Int))
(ret (con Int))
(params (own (con Int)))
(ret (own (con Int)))
(effects IO)))
(params n)
(body
+5 -5
View File
@@ -34,8 +34,8 @@
(doc "Return the FizzBuzz label for n, or the empty string if n is a plain number.")
(type
(fn-type
(params (con Int))
(ret (con Str))))
(params (own (con Int)))
(ret (own (con Str)))))
(params n)
(body
(if (app eq (app % n 15) 0)
@@ -48,7 +48,7 @@
(fn emit_one
(doc "Print the FizzBuzz label or the number itself.")
(type (fn-type (params (con Int)) (ret (con Unit)) (effects IO)))
(type (fn-type (params (own (con Int))) (ret (own (con Unit))) (effects IO)))
(params n)
(body
(let label (app classify n)
@@ -58,7 +58,7 @@
(fn loop
(doc "Tail-recursive driver over [i..stop].")
(type (fn-type (params (con Int) (con Int)) (ret (con Unit)) (effects IO)))
(type (fn-type (params (own (con Int)) (own (con Int))) (ret (own (con Unit))) (effects IO)))
(params i stop)
(body
(if (app gt i stop)
@@ -68,6 +68,6 @@
(tail-app loop (app + i 1) stop)))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app loop 1 15))))
+1 -1
View File
@@ -40,7 +40,7 @@
(app eq (app * a d) (app * b c)))))))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let r_1_2 (term-ctor Rational MkRational 1 2)
+4 -4
View File
@@ -25,7 +25,7 @@
(fn fabs
(doc "Float absolute value via the named-fn comparison surface.")
(type (fn-type (params (con Float)) (ret (con Float))))
(type (fn-type (params (own (con Float))) (ret (own (con Float)))))
(params x)
(body
(if (app float_lt x 0.0)
@@ -34,7 +34,7 @@
(fn iterate
(doc "Tail-recursive Newton iteration. Stops when |xnew - x| < tol.")
(type (fn-type (params (con Float) (con Float) (con Float)) (ret (con Float))))
(type (fn-type (params (own (con Float)) (own (con Float)) (own (con Float))) (ret (own (con Float)))))
(params n x tol)
(body
(let xnew (app / (app + x (app / n x)) 2.0)
@@ -44,7 +44,7 @@
(fn sqrt
(doc "sqrt n via Newton with initial guess 1.0 and tolerance 1e-10. Returns 0.0 for n == 0.0; assumes n >= 0.")
(type (fn-type (params (con Float)) (ret (con Float))))
(type (fn-type (params (own (con Float))) (ret (own (con Float)))))
(params n)
(body
(if (app float_eq n 0.0)
@@ -52,7 +52,7 @@
(app iterate n 1.0 0.0000000001))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq (app print (app sqrt 4.0))
@@ -18,6 +18,6 @@
(module eqord_4_float_ord_must_fail
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (if (app lt 1.5 2.5) 1 0)))))
@@ -11,6 +11,6 @@
(module eqord_5_float_eq_must_fail
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (if (app eq 1.5 1.5) 1 0)))))
+4 -4
View File
@@ -14,8 +14,8 @@
(doc "Recurse k times applying x' = 0.5 * (x + n/x).")
(type
(fn-type
(params (con Float) (con Float) (con Int))
(ret (con Float))))
(params (own (con Float)) (own (con Float)) (own (con Int)))
(ret (own (con Float)))))
(params n x k)
(body
(if (app eq k 0)
@@ -27,12 +27,12 @@
(fn sqrt
(doc "20-step Newton iteration starting from x0 = n.")
(type (fn-type (params (con Float)) (ret (con Float))))
(type (fn-type (params (own (con Float))) (ret (own (con Float)))))
(params n)
(body (app newton_iter n n 20)))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (app sqrt 2.0)))))
@@ -22,8 +22,8 @@
(doc "Tail-recursive sum with accumulator.")
(type
(fn-type
(params (con IntList) (con Int))
(ret (con Int))))
(params (borrow (con IntList)) (own (con Int)))
(ret (own (con Int)))))
(params xs acc)
(body
(match xs
@@ -35,8 +35,8 @@
(doc "Tail-recursive length with accumulator.")
(type
(fn-type
(params (con IntList) (con Int))
(ret (con Int))))
(params (borrow (con IntList)) (own (con Int)))
(ret (own (con Int)))))
(params xs acc)
(body
(match xs
@@ -46,7 +46,7 @@
(fn mean
(doc "Mean as Float = sum / count, both promoted via int_to_float.")
(type (fn-type (params (con IntList)) (ret (con Float))))
(type (fn-type (params (borrow (con IntList))) (ret (own (con Float)))))
(params xs)
(body
(app /
@@ -54,7 +54,7 @@
(app int_to_float (app count_acc xs 0)))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print
@@ -32,7 +32,7 @@
(fn classify
(doc "-1=NaN, 0=infinite, 1=finite. Uses is_nan + abs > huge.")
(type (fn-type (params (con Float)) (ret (con Int))))
(type (fn-type (params (own (con Float))) (ret (own (con Int)))))
(params x)
(body
(if (app is_nan x)
@@ -44,7 +44,7 @@
1)))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq (app print (app / 6.0 3.0))
@@ -20,7 +20,7 @@
(module floats_4_float_to_str_reach
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(do io/print_str (app float_to_str 3.14)))))
+5 -5
View File
@@ -4,8 +4,8 @@
(doc "Tail-recursive factorial accumulator: fact_acc(n, acc) = n!*acc.")
(type
(fn-type
(params (con Int) (con Int))
(ret (con Int))))
(params (own (con Int)) (own (con Int)))
(ret (own (con Int)))))
(params n acc)
(body
(if (app eq n 0)
@@ -16,13 +16,13 @@
(doc "Factorial of a non-negative Int.")
(type
(fn-type
(params (con Int))
(ret (con Int))))
(params (own (con Int)))
(ret (own (con Int)))))
(params n)
(body (app fact_acc n 1)))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq
+1 -1
View File
@@ -21,7 +21,7 @@
(case (pat-ctor Blue) "Blue")))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq
@@ -4,7 +4,7 @@
(doc "A user-defined typeclass: produce a short Str describing a value.")
(param a)
(method describe
(type (fn-type (params (borrow a)) (ret (con Str))))))
(type (fn-type (params (borrow a)) (ret (own (con Str)))))))
(data Shape
(ctor Circle (con Int))
@@ -42,13 +42,13 @@
(constraints (constraint Describe a))
(fn-type
(params (borrow a))
(ret (con Unit))
(ret (own (con Unit)))
(effects IO))))
(params x)
(body (do io/print_str (app describe x))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq
+3 -3
View File
@@ -2,19 +2,19 @@
(fn square
(doc "Multiply an Int by itself.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params x)
(body (app * x x)))
(fn cube
(doc "Raise an Int to the third power.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params x)
(body (app * x (app square x))))
(fn abs_int
(doc "Absolute value of an Int.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params x)
(body
(if (app lt x 0)
+1 -1
View File
@@ -3,7 +3,7 @@
(import forma_4_intmath_lib)
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq
@@ -16,13 +16,13 @@
(fn add
(doc "Plain Int addition. Used as the (b, a) -> b arg to List.fold_left.")
(type (fn-type (params (con Int) (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int)) (own (con Int))) (ret (own (con Int)))))
(params acc x)
(body (app + acc x)))
(fn main
(doc "Build a List<Int> of [1,2,3,4,5], print its length (5), then its sum (15).")
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let xs
+2 -2
View File
@@ -20,12 +20,12 @@
(fn new
(doc "Build a Counter initialised to the given value.")
(type (fn-type (params (con Int)) (ret (con Counter))))
(type (fn-type (params (own (con Int))) (ret (own (con Counter)))))
(params n)
(body (term-ctor Counter MkCounter n)))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let c (new Counter 42)
+2 -2
View File
@@ -10,12 +10,12 @@
(ctor MkCounter (con Int)))
(fn value
(type (fn-type (params (con Counter)) (ret (con Int))))
(type (fn-type (params (borrow (con Counter))) (ret (own (con Int)))))
(params c)
(body (match c (case (pat-ctor MkCounter x) x))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let c (term-ctor Counter MkCounter 41)
@@ -17,12 +17,12 @@
(fn unwrap
(doc "Project the contained Int out of a NumBox<Int>.")
(type (fn-type (params (con NumBox (con Int))) (ret (con Int))))
(type (fn-type (params (own (con NumBox (con Int)))) (ret (own (con Int)))))
(params b)
(body (match b (case (pat-ctor MkNumBox x) x))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let b (term-ctor NumBox MkNumBox 17)
+2 -2
View File
@@ -13,11 +13,11 @@
(fn unwrap_str
(doc "BAD: NumBox is restricted to {Int, Float}, but we ask for Str. Expected: ParamNotInRestrictedSet on the type signature.")
(type (fn-type (params (con NumBox (con Str))) (ret (con Str))))
(type (fn-type (params (own (con NumBox (con Str)))) (ret (own (con Str)))))
(params b)
(body (match b (case (pat-ctor MkNumBox x) x))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (do io/print_str ""))))
@@ -1,7 +1,7 @@
(module loop_recur_1_isqrt_newton
(fn main
(doc "Integer square root of 152399025 (= 12345^2) via Newton's method, then a sanity-difference. Expected stdout: 12345 then 0.")
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let r (app isqrt 152399025)
@@ -9,7 +9,7 @@
(app print (app - r 12345))))))
(fn isqrt
(doc "Newton's method for floor(sqrt(n)). Two binders: x (current guess) and prev (previous guess, to detect the fixpoint/2-cycle). The recur is buried inside a nested if, not at body toplevel.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params n)
(body
(if (app lt n 2)
+2 -2
View File
@@ -1,7 +1,7 @@
(module loop_recur_2_collatz
(fn main
(doc "Collatz step counts. collatz_len(27)=111, collatz_len(97)=118, collatz_len(1)=0. Expected stdout (per line): 111, 118, 0.")
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq (app print (app collatz_len 27))
@@ -9,7 +9,7 @@
(app print (app collatz_len 1))))))
(fn collatz_len
(doc "Number of Collatz steps to reach 1. Two binders: n (current value) and steps (accumulator). Parity dispatch is a `match` on n%2; the recur lives in the tail of each match arm, not at body toplevel.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params start)
(body
(loop (n (con Int) start) (steps (con Int) 0)
@@ -4,13 +4,13 @@
; Expected: `ail check` exits 1 with code recur-outside-loop.
(module loop_recur_3a_recur_outside_loop
(fn countdown
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params n)
(body
(if (app eq n 0)
0
(recur (app - n 1)))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (app countdown 5)))))
@@ -4,7 +4,7 @@
; Expected: `ail check` exits 1 with code recur-arity-mismatch.
(module loop_recur_3b_recur_arity
(fn sum_to
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params n)
(body
(loop (acc (con Int) 0) (i (con Int) 1)
@@ -12,6 +12,6 @@
acc
(recur (app + acc i))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (app sum_to 10)))))
@@ -4,7 +4,7 @@
; Expected: `ail check` exits 1 with code recur-type-mismatch.
(module loop_recur_3c_recur_type
(fn count_down
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params start)
(body
(loop (i (con Int) start)
@@ -12,6 +12,6 @@
i
(recur (app gt i 0))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (app count_down 5)))))
@@ -5,7 +5,7 @@
; Expected: `ail check` exits 1 with code recur-not-in-tail-position.
(module loop_recur_3d_recur_not_tail
(fn factorial
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params n)
(body
(loop (i (con Int) n)
@@ -13,6 +13,6 @@
1
(app * i (recur (app - i 1)))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (app factorial 5)))))
@@ -5,11 +5,11 @@
; Expected: `ail check` exits 1 with code loop-binder-captured-by-lambda.
(module loop_recur_3e_binder_captured
(fn apply_int
(type (fn-type (params (fn-type (params (con Int)) (ret (con Int))) (con Int)) (ret (con Int))))
(type (fn-type (params (own (fn-type (params (own (con Int))) (ret (own (con Int))))) (own (con Int))) (ret (own (con Int)))))
(params f x)
(body (app f x)))
(fn sum_to
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params n)
(body
(loop (acc (con Int) 0) (i (con Int) 1)
@@ -18,6 +18,6 @@
(recur (app apply_int (lam (params (typed d (con Int))) (ret (con Int)) (body (app + acc d))) i)
(app + i 1))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (app sum_to 10)))))
@@ -10,7 +10,7 @@
(module loop_recur_4_gcd_value_pos
(fn gcd
(doc "Euclidean gcd via loop/recur. Two binders a,b; recur in the tail of the else branch.")
(type (fn-type (params (con Int) (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int)) (own (con Int))) (ret (own (con Int)))))
(params x y)
(body
(loop (a (con Int) x) (b (con Int) y)
@@ -18,7 +18,7 @@
a
(recur b (app % a b))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (app + (app gcd 48 18) (app gcd 1071 462))))))
@@ -6,7 +6,7 @@
(module loop_recur_5_event_loop_noterm
(fn run_forever
(doc "Infinite event loop. Two binders: tick counter and a running parity flag. No branch ever exits via a non-recur term.")
(type (fn-type (params) (ret (con Int))))
(type (fn-type (params) (ret (own (con Int)))))
(params)
(body
(loop (tick (con Int) 0) (parity (con Int) 0)
@@ -14,6 +14,6 @@
(recur (app + tick 1) 1)
(recur (app + tick 1) 0)))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (app run_forever)))))
@@ -8,7 +8,7 @@
(module loop_recur_5b_event_loop_noterm
(fn run_forever
(doc "Infinite event loop. Two binders: tick counter and a running parity flag. No branch ever exits via a non-recur term.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params start)
(body
(loop (tick (con Int) start) (parity (con Int) 0)
@@ -16,6 +16,6 @@
(recur (app + tick 1) 1)
(recur (app + tick 1) 0)))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body (app print (app run_forever 0)))))
+1 -1
View File
@@ -3,7 +3,7 @@
(module mut-local_1_factorial
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (let prod 1 (let prod (app * prod 1) (let prod (app * prod 2) (let prod (app * prod 3) (let prod (app * prod 4) (let prod (app * prod 5) prod))))))))))
@@ -5,12 +5,12 @@
(fn classify
(doc "Return category code 0..3 for temperature t in degrees C.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params t)
(body (let code 0 (let code (if (app lt t 0) 0 (if (app lt t 15) 1 (if (app lt t 28) 2 3))) code))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (app classify 22)))))
+1 -1
View File
@@ -4,7 +4,7 @@
(module mut-local_3_horner
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (let acc 2.0 (let acc (app - (app * acc 2.5) 3.0) (let acc (app + (app * acc 2.5) 5.0) (let acc (app - (app * acc 2.5) 7.0) acc))))))))
@@ -5,12 +5,12 @@
(module mut-local_4_has_small_factor
(fn has_small_factor
(type (fn-type (params (con Int)) (ret (con Bool))))
(type (fn-type (params (own (con Int))) (ret (own (con Bool)))))
(params n)
(body (let found false (let found (if (app eq (app % n 2) 0) true found) (let found (if (app eq (app % n 3) 0) true found) (let found (if (app eq (app % n 5) 0) true found) (let found (if (app eq (app % n 7) 0) true found) found)))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (app has_small_factor 91)))))
+3 -3
View File
@@ -28,7 +28,7 @@
(fn fill
(doc "Fill slots 0..n of buf with (i*i + 1). Linear: own in, own out.")
(type (fn-type (params (own (con RawBuf (con Int))) (con Int)) (ret (own (con RawBuf (con Int))))))
(type (fn-type (params (own (con RawBuf (con Int))) (own (con Int))) (ret (own (con RawBuf (con Int))))))
(params buf n)
(body
(loop (b (con RawBuf (con Int)) buf) (i (con Int) 0)
@@ -39,7 +39,7 @@
(fn total
(doc "Sum every slot of buf, driving the bound off RawBuf.size.")
(type (fn-type (params (borrow (con RawBuf (con Int)))) (ret (con Int))))
(type (fn-type (params (borrow (con RawBuf (con Int)))) (ret (own (con Int)))))
(params buf)
(body
(loop (acc (con Int) 0) (i (con Int) 0)
@@ -49,7 +49,7 @@
(app + i 1))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let buf (new RawBuf (con Int) 5)
+1 -1
View File
@@ -21,7 +21,7 @@
(module rawbuf_2_running_max
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let buf (new RawBuf (con Int) 4)
+1 -1
View File
@@ -16,7 +16,7 @@
(module rawbuf_3_sensor_pair
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let readings (new RawBuf (con Float) 3)
@@ -30,6 +30,6 @@
(fn first_price
(doc "Read the first Tick out of a batch buffer. Should never check: RawBuf cannot hold a user ADT.")
(type (fn-type (params (borrow (con RawBuf (con Tick)))) (ret (con Tick))))
(type (fn-type (params (borrow (con RawBuf (con Tick)))) (ret (own (con Tick)))))
(params batch)
(body (app RawBuf.get batch 0))))
@@ -41,7 +41,7 @@
(fn build_window
(doc "Allocate a 4-slot Float buffer, fill slot i with (2*(i+1)), wrap in a Window with count=4.")
(type (fn-type (params (con Int)) (ret (own (con Window)))))
(type (fn-type (params (own (con Int))) (ret (own (con Window)))))
(params n)
(body
(let buf (new RawBuf (con Float) 4)
@@ -55,7 +55,7 @@
(fn mean
(doc "Average of the first count slots, read through a borrow of the Window.")
(type (fn-type (params (borrow (con Window))) (ret (con Float))))
(type (fn-type (params (borrow (con Window))) (ret (own (con Float)))))
(params w)
(body
(match w
@@ -70,7 +70,7 @@
(fn wmax
(doc "Maximum of the first count slots, read through a borrow of the Window.")
(type (fn-type (params (borrow (con Window))) (ret (con Float))))
(type (fn-type (params (borrow (con Window))) (ret (own (con Float)))))
(params w)
(body
(match w
@@ -84,7 +84,7 @@
(app + i 1))))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let w (app build_window 4)
+3 -3
View File
@@ -28,7 +28,7 @@
(fn mark_even
(doc "Set slot i to (i is even) for i in 0..n. Linear own->own.")
(type (fn-type (params (own (con RawBuf (con Bool))) (con Int)) (ret (own (con RawBuf (con Bool))))))
(type (fn-type (params (own (con RawBuf (con Bool))) (own (con Int))) (ret (own (con RawBuf (con Bool))))))
(params buf n)
(body
(loop (b (con RawBuf (con Bool)) buf) (i (con Int) 0)
@@ -39,7 +39,7 @@
(fn count_set
(doc "Count the set flags, reading the Bool buffer through a borrow.")
(type (fn-type (params (borrow (con RawBuf (con Bool)))) (ret (con Int))))
(type (fn-type (params (borrow (con RawBuf (con Bool)))) (ret (own (con Int)))))
(params buf)
(body
(loop (acc (con Int) 0) (i (con Int) 0)
@@ -49,7 +49,7 @@
(app + i 1))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let buf (new RawBuf (con Bool) 6)
@@ -17,12 +17,12 @@
(fn make_presence
(doc "Try to allocate a RawBuf of Unit — forbidden element type.")
(type (fn-type (params (con Int)) (ret (own (con RawBuf (con Unit))))))
(type (fn-type (params (own (con Int))) (ret (own (con RawBuf (con Unit))))))
(params n)
(body (new RawBuf (con Unit) n)))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let buf (app make_presence 3)
@@ -28,7 +28,7 @@
(fn fill
(doc "Fill slot i with fib(i) for i in 0..n. Linear own->own.")
(type (fn-type (params (own (con RawBuf (con Int))) (con Int)) (ret (own (con RawBuf (con Int))))))
(type (fn-type (params (own (con RawBuf (con Int))) (own (con Int))) (ret (own (con RawBuf (con Int))))))
(params buf n)
(body
; Seed slots 0 and 1 to 1, then each later slot = sum of prior two,
@@ -45,7 +45,7 @@
(fn total
(doc "Sum every slot, borrow receiver.")
(type (fn-type (params (borrow (con RawBuf (con Int)))) (ret (con Int))))
(type (fn-type (params (borrow (con RawBuf (con Int)))) (ret (own (con Int)))))
(params buf)
(body
(loop (acc (con Int) 0) (i (con Int) 0)
@@ -56,7 +56,7 @@
(fn argmax
(doc "Index of the largest slot, borrow receiver. Tracks (best_i, best_v).")
(type (fn-type (params (borrow (con RawBuf (con Int)))) (ret (con Int))))
(type (fn-type (params (borrow (con RawBuf (con Int)))) (ret (own (con Int)))))
(params buf)
(body
(loop (best_i (con Int) 0) (best_v (con Int) (app RawBuf.get buf 0)) (i (con Int) 0)
@@ -67,7 +67,7 @@
(recur best_i best_v (app + i 1)))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let buf (new RawBuf (con Int) 6)
@@ -14,7 +14,7 @@
(fn sum_sq
(doc "Sum of i*i for i in 1..=n via loop/recur. Two binders: i (counter), acc (running total).")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params n)
(body
(loop (i (con Int) 1) (acc (con Int) 0)
@@ -23,7 +23,7 @@
(recur (app + i 1) (app + acc (app * i i)))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (app sum_sq 10)))))
@@ -19,7 +19,7 @@
(fn grade
(doc "Letter-grade code (4=A..0=F) from a numeric score, written as the let-threaded equivalent of a mutable cascade.")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params score)
(body
(let g 0
@@ -30,7 +30,7 @@
g)))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq (app print (app grade 95))
@@ -18,7 +18,7 @@
(fn poly
(doc "Horner-form evaluation of 2x^4+3x^3+0x^2+5x+7 as a straight-line let chain (the faithful let/if form of a mutable acc).")
(type (fn-type (params (con Int)) (ret (con Int))))
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
(params x)
(body
(let acc 2
@@ -29,7 +29,7 @@
acc)))))))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(app print (app poly 2)))))
@@ -39,8 +39,8 @@
(doc "Thread (rest, depth, ok). Each arm updates a subset of state; the unchanged components must be restated in every tail call.")
(type
(fn-type
(params (own (con TokStream)) (con Int) (con Bool))
(ret (con Bool))))
(params (own (con TokStream)) (own (con Int)) (own (con Bool)))
(ret (own (con Bool)))))
(params rest depth ok)
(body
(match rest
@@ -58,12 +58,12 @@
(tail-app scan more depth ok)))))))
(fn balanced
(type (fn-type (params (own (con TokStream))) (ret (con Bool))))
(type (fn-type (params (own (con TokStream))) (ret (own (con Bool)))))
(params s)
(body (app scan s 0 true)))
(fn main
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(seq