; Fieldtest cut55-4b — decision (d), the correct way to project out of a borrow.
;
; After borrow-return is rejected, the author returns `(own ...)` and uses
; `(clone X)` (the explicit RC inc from contract 0008) to lift a borrowed
; field into an owned value that may legally escape. head_clone borrows
; xs, reads its head h (an Int value — copied freely), and returns it own.
; For the heap-tail case we clone the tail to return an owned view.
;
; This is the "did the author find the clone escape hatch?" check.
;
; Expected: ail check -> ok. ail run -> prints 10 (head of [10,20,30]).

(module cut55_4b_clone_to_return

  (data List
    (ctor Nil)
    (ctor Cons (con Int) (con List)))

  (fn head_or_zero
    (doc "Borrow xs; return its head Int (value type, copied) or 0.")
    (type
      (fn-type
        (params (borrow (con List)))
        (ret (own (con Int)))))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Nil) 0)
        (case (pat-ctor Cons h t) h))))

  (fn tail_copy
    (doc "Borrow xs; return an OWNED copy of the tail via clone (escape hatch).")
    (type
      (fn-type
        (params (borrow (con List)))
        (ret (own (con List)))))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Nil) (term-ctor List Nil))
        (case (pat-ctor Cons h t) (clone t)))))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (let xs
        (term-ctor List Cons 10
          (term-ctor List Cons 20
            (term-ctor List Nil)))
        (seq (app print (app head_or_zero xs)) (do io/print_str "\n"))))))
