;; showadt.hs — `deriving (Show)` on a multi-constructor recursive ADT.
;; Source: classic exposition example, e.g. Real World Haskell ch.6.
;;
;; Exercises Phase 8: `deriving (Show)` on an ADT whose constructors recurse
;; into themselves; precedence-based paren wrapping for nested arguments;
;; `print` from the prelude (which is `putStrLn (show x)`).

(define
  hk-showadt-source
  "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\n\nmain = do\n  print (Lit 3)\n  print (Add (Lit 1) (Lit 2))\n  print (Mul (Lit 3) (Add (Lit 4) (Lit 5)))\n")

(hk-test
  "showadt.hs — main prints three lines"
  (hk-run-io hk-showadt-source)
  (list "Lit 3" "Add (Lit 1) (Lit 2)" "Mul (Lit 3) (Add (Lit 4) (Lit 5))"))

(hk-test
  "showadt.hs — show Lit 3"
  (hk-deep-force
    (hk-run
      "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Lit 3)"))
  "Lit 3")

(hk-test
  "showadt.hs — show Add wraps both args"
  (hk-deep-force
    (hk-run
      "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Add (Lit 1) (Lit 2))"))
  "Add (Lit 1) (Lit 2)")

(hk-test
  "showadt.hs — fully nested Mul of Adds"
  (hk-deep-force
    (hk-run
      "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Mul (Add (Lit 1) (Lit 2)) (Add (Lit 3) (Lit 4)))"))
  "Mul (Add (Lit 1) (Lit 2)) (Add (Lit 3) (Lit 4))")

(hk-test
  "showadt.hs — Lit with negative literal wraps int in parens"
  (hk-deep-force
    (hk-run
      "data Expr = Lit Int | Add Expr Expr | Mul Expr Expr deriving (Show)\nmain = show (Lit (negate 7))"))
  "Lit (-7)")

{:fails hk-test-fails :pass hk-test-pass :fail hk-test-fail}
