; Iter 18a — `(borrow T)` and `(own T)` mode annotations on
; fn-type params and ret slots.
;
; This fixture exercises the schema/parser/printer/typechecker path
; that Iter 18a adds. It does *not* exercise enforcement: under the
; semantics shipping with 18a, every mode is treated as
; `Implicit ≡ Own` and `(borrow ...)` / `(own ...)` are accepted but
; have no codegen consequence. Linearity / borrow checking comes in
; Iter 18c.
;
; What round-trips through the form-A printer:
;   (borrow (con List))   — list_length's xs parameter
;   (own (con List))      — sum_list's xs parameter
;
; Expected stdout (one int per line, via io/print_int + a newline):
;   3
;   6

(module borrow_own_demo

  (data List
    (doc "Monomorphic singly-linked Int list — boxed, recursive.")
    (ctor Nil)
    (ctor Cons (con Int) (con List)))

  (fn list_length
    (doc "Borrow xs, count its elements. Iter 18a: `(borrow (con List))`.")
    (type
      (fn-type
        (params (borrow (con List)))
        (ret (con Int))))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Nil) 0)
        (case (pat-ctor Cons h t)
          (app + 1 (app list_length t))))))

  (fn sum_list
    (doc "Consume xs, sum its elements. Iter 18a: `(own (con List))`.")
    (type
      (fn-type
        (params (own (con List)))
        (ret (con Int))))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Nil) 0)
        (case (pat-ctor Cons h t)
          (app + h (app sum_list t))))))

  (fn main
    (doc "Build [1,2,3]; print list_length (3) then sum_list (6).")
    (type (fn-type (params) (ret (con Unit)) (effects IO)))
    (params)
    (body
      (let xs
        (term-ctor List Cons 1
          (term-ctor List Cons 2
            (term-ctor List Cons 3
              (term-ctor List Nil))))
        (seq
          (do io/print_int (app list_length xs))
          (do io/print_int (app sum_list xs)))))))
