; Axis: a small streaming-feel state machine threading MORE THAN
; ONE piece of state, updating only a SUBSET per branch.
;
; Scan a token stream (a recursive Int list; 1 = '(', 2 = ')',
; 0 = any other token) and decide if the brackets are balanced.
;
; Imperative instinct (exactly what `mut` would invite):
;   depth = 0
;   ok    = true
;   for t in stream:
;       if t == 1:                 depth = depth + 1          ; only depth changes
;       elif t == 2:
;           if depth == 0: ok = false                          ; only ok changes
;           else:          depth = depth - 1                    ; only depth changes
;       ; t == 0 -> neither changes
;   return ok && depth == 0
;
; Surviving-surface shape: a recursive scanner fn threading
; (rest, depth, ok) — `loop`/`recur` cannot walk an ADT (it rebinds
; positionally, there is no structural pattern in a recur), so the
; stream traversal is ordinary tail recursion; the per-branch
; "update a subset of the state" becomes "pass the unchanged values
; through unchanged". This is the task that most stresses the
; removal: an imperative author updates one variable and leaves the
; others implicitly alone; here every recur must restate all three.
;
; balanced "(()())"  -> true   ; stream 1 1 2 1 2 2
; balanced ")("       -> false  ; stream 2 1
; Expected stdout (per line): true, false

(module remove-mut_4_bracket_scanner

  (data TokStream
    (doc "1='(' , 2=')' , 0=other.")
    (ctor Nil)
    (ctor Cons (con Int) (con TokStream)))

  (fn scan
    (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)) (own (con Int)) (own (con Bool)))
        (ret (own (con Bool)))))
    (params rest depth ok)
    (body
      (match rest
        (case (pat-ctor Nil)
          (if ok (app eq depth 0) false))
        (case (pat-ctor Cons t more)
          (match t
            (case (pat-lit 1)
              (tail-app scan more (app + depth 1) ok))
            (case (pat-lit 2)
              (if (app eq depth 0)
                  (tail-app scan more depth false)
                  (tail-app scan more (app - depth 1) ok)))
            (case _
              (tail-app scan more depth ok)))))))

  (fn balanced
    (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 (own (con Unit))) (effects IO)))
    (params)
    (body
      (seq
        (app print
          (app balanced
            (term-ctor TokStream Cons 1
              (term-ctor TokStream Cons 1
                (term-ctor TokStream Cons 2
                  (term-ctor TokStream Cons 1
                    (term-ctor TokStream Cons 2
                      (term-ctor TokStream Cons 2
                        (term-ctor TokStream Nil)))))))))
        (app print
          (app balanced
            (term-ctor TokStream Cons 2
              (term-ctor TokStream Cons 1
                (term-ctor TokStream Nil)))))))))
