; Fieldtest fixture — Axis 1: equality on primitive Int via `(app eq …)`.
;
; FizzBuzz over [1..15]:
;   if n % 15 == 0 print "FizzBuzz"
;   else if n % 3  == 0 print "Fizz"
;   else if n % 5  == 0 print "Buzz"
;   else print (show n)
;
; Equality dispatches through prelude.Eq.eq at Int (intercept arm
; eq__Int → `icmp eq i64`). Demonstrates the LLM-natural shape of
; `(app eq …)` on the primitive type that dominates most numerical
; code.
;
; Expected stdout (one per line):
;   1
;   2
;   Fizz
;   4
;   Buzz
;   Fizz
;   7
;   8
;   Fizz
;   Buzz
;   11
;   Fizz
;   13
;   14
;   FizzBuzz

(module eqord_1_fizzbuzz

  (fn classify
    (doc "Return the FizzBuzz label for n, or the empty string if n is a plain number.")
    (type
      (fn-type
        (params (own (con Int)))
        (ret (own (con Str)))))
    (params n)
    (body
      (if (app eq (app % n 15) 0)
        "FizzBuzz"
        (if (app eq (app % n 3) 0)
          "Fizz"
          (if (app eq (app % n 5) 0)
            "Buzz"
            "")))))

  (fn emit_one
    (doc "Print the FizzBuzz label or the number itself.")
    (type (fn-type (params (own (con Int))) (ret (own (con Unit))) (effects IO)))
    (params n)
    (body
      (let label (app classify n)
        (if (app eq label "")
          (app print n)
          (app print label)))))

  (fn loop
    (doc "Tail-recursive driver over [i..stop].")
    (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)
        (lit-unit)
        (seq
          (app emit_one i)
          (tail-app loop (app + i 1) stop)))))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body (app loop 1 15))))
