(module prelude
  (kernel)
  (data Ordering
    (doc "Result of a three-way comparison: LT (less than), EQ (equal), GT (greater than). Ships in milestone 23 as the codomain of Ord.compare.")
    (ctor LT)
    (ctor EQ)
    (ctor GT))
  (class Eq
    (param a)
    (doc "Structural equality. The class-method `eq` is the surface-level comparator; `==` as a surface name is not part of the language. Primitive instances Eq Int / Bool / Str / Unit are lowered via try_emit_primitive_instance_body in the codegen.")
    (method eq
      (type (fn-type (params (borrow a) (borrow a)) (ret (own (con Bool)))))))
  (instance
    (class Eq)
    (type (con Int))
    (doc "Eq Int. Compiler-supplied (intrinsic) body; codegen emits `icmp eq i64` with the alwaysinline attribute via the intercept registry.")
    (method eq
      (body (lam (params (typed x a) (typed y a)) (ret (con Bool)) (intrinsic)))))
  (instance
    (class Eq)
    (type (con Bool))
    (doc "Eq Bool. Compiler-supplied (intrinsic) body; codegen emits `icmp eq i1` with the alwaysinline attribute via the intercept registry.")
    (method eq
      (body (lam (params (typed x a) (typed y a)) (ret (con Bool)) (intrinsic)))))
  (instance
    (class Eq)
    (type (con Str))
    (doc "Eq Str. Compiler-supplied (intrinsic) body; codegen emits a call to `@ail_str_eq` with the alwaysinline attribute via the intercept registry.")
    (method eq
      (body (lam (params (typed x a) (typed y a)) (ret (con Bool)) (intrinsic)))))
  (instance
    (class Eq)
    (type (con Unit))
    (doc "Eq Unit. Unit is single-inhabitant so all values compare equal. Compiler-supplied (intrinsic) body; codegen emits `ret i1 1` via the intercept registry.")
    (method eq
      (body (lam (params (typed x a) (typed y a)) (ret (con Bool)) (intrinsic)))))
  (class Ord
    (param a)
    (superclass (class Eq) (type a))
    (doc "Total ordering. Ships in milestone 23 alongside Eq. `compare x y` returns LT, EQ, or GT (the three-ctor Ordering ADT also in the prelude). Decision 11's single-superclass closure requires `instance Eq T` for every `instance Ord T` — the three Ord instances below pair with the three Eq instances shipped in iter 23.2.3.")
    (method compare
      (type (fn-type (params (borrow a) (borrow a)) (ret (own (con Ordering)))))))
  (instance
    (class Ord)
    (type (con Int))
    (doc "Ord Int. Compiler-supplied (intrinsic) body; codegen emits a three-way `icmp slt` / `icmp eq` branch ladder constructing LT / EQ / GT via the intercept registry.")
    (method compare
      (body (lam (params (typed x a) (typed y a)) (ret (con Ordering)) (intrinsic)))))
  (instance
    (class Ord)
    (type (con Bool))
    (doc "Ord Bool. Compiler-supplied (intrinsic) body; codegen emits `icmp ult i1` LT-test, `icmp eq i1` EQ-test, GT default, via the intercept registry.")
    (method compare
      (body (lam (params (typed x a) (typed y a)) (ret (con Ordering)) (intrinsic)))))
  (instance
    (class Ord)
    (type (con Str))
    (doc "Ord Str. Compiler-supplied (intrinsic) body; codegen emits `call i32 @ail_str_compare(ptr, ptr)` then branches on slt-0 / eq-0 against the normalised {-1, 0, +1} return, via the intercept registry.")
    (method compare
      (body (lam (params (typed x a) (typed y a)) (ret (con Ordering)) (intrinsic)))))
  (class Show
    (param a)
    (doc "Producer of a human-readable Str representation. Ships in milestone 24 with primitive instances for Int/Bool/Str/Float; user types declare their own instance.")
    (method show
      (type (fn-type (params (borrow a)) (ret (own (con Str)))))))
  (instance
    (class Show)
    (type (con Int))
    (method show
      (body (lam (params (typed x (con Int))) (ret (con Str)) (body (app int_to_str x))))))
  (instance
    (class Show)
    (type (con Bool))
    (method show
      (body (lam (params (typed x (con Bool))) (ret (con Str)) (body (app bool_to_str x))))))
  (instance
    (class Show)
    (type (con Str))
    (method show
      (body (lam (params (typed x (con Str))) (ret (con Str)) (body (app str_clone x))))))
  (instance
    (class Show)
    (type (con Float))
    (method show
      (body (lam (params (typed x (con Float))) (ret (con Str)) (body (app float_to_str x))))))
  (fn ne
    (doc "Polymorphic disequality. `ne x y` ≡ not (eq x y). Ships in milestone 23 as the Eq-class free helper.")
    (type (forall (vars a) (constraints (constraint Eq a)) (fn-type (params (borrow a) (borrow a)) (ret (own (con Bool))))))
    (params x y)
    (body (app not (app eq x y))))
  (fn lt
    (doc "Polymorphic strict-less-than. `lt x y` ≡ case compare x y of LT -> True; _ -> False. Ships in milestone 23 as the Ord-class free helper.")
    (type (forall (vars a) (constraints (constraint Ord a)) (fn-type (params (borrow a) (borrow a)) (ret (own (con Bool))))))
    (params x y)
    (body (match (app compare x y)
      (case (pat-ctor LT) true)
      (case _ false))))
  (fn le
    (doc "Polymorphic less-than-or-equal. `le x y` ≡ case compare x y of GT -> False; _ -> True. Ships in milestone 23 as the Ord-class free helper.")
    (type (forall (vars a) (constraints (constraint Ord a)) (fn-type (params (borrow a) (borrow a)) (ret (own (con Bool))))))
    (params x y)
    (body (match (app compare x y)
      (case (pat-ctor GT) false)
      (case _ true))))
  (fn gt
    (doc "Polymorphic strict-greater-than. `gt x y` ≡ case compare x y of GT -> True; _ -> False. Ships in milestone 23 as the Ord-class free helper.")
    (type (forall (vars a) (constraints (constraint Ord a)) (fn-type (params (borrow a) (borrow a)) (ret (own (con Bool))))))
    (params x y)
    (body (match (app compare x y)
      (case (pat-ctor GT) true)
      (case _ false))))
  (fn ge
    (doc "Polymorphic greater-than-or-equal. `ge x y` ≡ case compare x y of LT -> False; _ -> True. Ships in milestone 23 as the Ord-class free helper.")
    (type (forall (vars a) (constraints (constraint Ord a)) (fn-type (params (borrow a) (borrow a)) (ret (own (con Bool))))))
    (params x y)
    (body (match (app compare x y)
      (case (pat-ctor LT) false)
      (case _ true))))
  (fn print
    (doc "Polymorphic console-print helper. `print x` ≡ `do io/print_str (show x)` with an explicit let-binder around `show x` for heap-Str RC discipline per eob.1 Str carve-out. Ships in milestone 24 as the second half of the Show prelude.")
    (type (forall (vars a) (constraints (constraint Show a)) (fn-type (params (borrow a)) (ret (own (con Unit))) (effects IO))))
    (params x)
    (body (let s (app show x) (do io/print_str s))))
  (fn float_eq
    (doc "IEEE Float equality. `float_eq x y` returns true iff both operands are non-NaN and bit-equal. Compiler-supplied (intrinsic) body; codegen emits `fcmp oeq double` with alwaysinline via the intercept registry. Replaces the milestone-deleted polymorphic `==` on Float.")
    (type (fn-type (params (own (con Float)) (own (con Float))) (ret (own (con Bool)))))
    (params x y)
    (intrinsic))
  (fn float_ne
    (doc "IEEE Float disequality. `float_ne nan nan` returns true (unordered-or-not-equal per IEEE-754). Compiler-supplied (intrinsic) body; codegen emits `fcmp une double`.")
    (type (fn-type (params (own (con Float)) (own (con Float))) (ret (own (con Bool)))))
    (params x y)
    (intrinsic))
  (fn float_lt
    (doc "IEEE Float strict less-than. `float_lt nan x` returns false for any x (unordered). Compiler-supplied (intrinsic) body; codegen emits `fcmp olt double`.")
    (type (fn-type (params (own (con Float)) (own (con Float))) (ret (own (con Bool)))))
    (params x y)
    (intrinsic))
  (fn float_le
    (doc "IEEE Float less-than-or-equal. Compiler-supplied (intrinsic) body; codegen emits `fcmp ole double`.")
    (type (fn-type (params (own (con Float)) (own (con Float))) (ret (own (con Bool)))))
    (params x y)
    (intrinsic))
  (fn float_gt
    (doc "IEEE Float strict greater-than. Compiler-supplied (intrinsic) body; codegen emits `fcmp ogt double`.")
    (type (fn-type (params (own (con Float)) (own (con Float))) (ret (own (con Bool)))))
    (params x y)
    (intrinsic))
  (fn float_ge
    (doc "IEEE Float greater-than-or-equal. Compiler-supplied (intrinsic) body; codegen emits `fcmp oge double`.")
    (type (fn-type (params (own (con Float)) (own (con Float))) (ret (own (con Bool)))))
    (params x y)
    (intrinsic)))
