;; Phase 15 — IORef unit tests.

(hk-test
  "newIORef + readIORef returns initial value"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef 42; v <- IORef.readIORef r; return v }"))
  (list "IO" 42))

(hk-test
  "writeIORef updates the cell"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef 0; IORef.writeIORef r 99; v <- IORef.readIORef r; return v }"))
  (list "IO" 99))

(hk-test
  "writeIORef returns IO ()"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef 0; IORef.writeIORef r 1 }"))
  (list "IO" (list "Tuple")))

(hk-test
  "modifyIORef applies a function"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef 5; IORef.modifyIORef r (\\x -> x * 2); v <- IORef.readIORef r; return v }"))
  (list "IO" 10))

(hk-test
  "modifyIORef' (strict) applies a function"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef 7; IORef.modifyIORef' r (\\x -> x + 3); v <- IORef.readIORef r; return v }"))
  (list "IO" 10))

(hk-test
  "two reads return the same value"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef 11; a <- IORef.readIORef r; b <- IORef.readIORef r; return (a + b) }"))
  (list "IO" 22))

(hk-test
  "shared ref across do-steps: write then read"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef 1; IORef.writeIORef r 2; IORef.writeIORef r 3; v <- IORef.readIORef r; return v }"))
  (list "IO" 3))

(hk-test
  "two refs are independent"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r1 <- IORef.newIORef 1; r2 <- IORef.newIORef 2; IORef.writeIORef r1 10; a <- IORef.readIORef r1; b <- IORef.readIORef r2; return (a + b) }"))
  (list "IO" 12))

(hk-test
  "string-valued IORef"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef \"hi\"; IORef.writeIORef r \"bye\"; v <- IORef.readIORef r; return v }"))
  (list "IO" "bye"))

(hk-test
  "list-valued IORef + cons"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nmain = do { r <- IORef.newIORef [1,2,3]; IORef.modifyIORef r (\\xs -> 0 : xs); v <- IORef.readIORef r; return v }"))
  (list
    "IO"
    (list ":" 0 (list ":" 1 (list ":" 2 (list ":" 3 (list "[]")))))))

(hk-test
  "counter loop: increment N times"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nloop r 0 = return ()\nloop r n = do { IORef.modifyIORef r (\\x -> x + 1); loop r (n - 1) }\nmain = do { r <- IORef.newIORef 0; loop r 10; v <- IORef.readIORef r; return v }"))
  (list "IO" 10))

(hk-test
  "modifyIORef' inside a loop"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\ngo r 0 = return ()\ngo r n = do { IORef.modifyIORef' r (\\x -> x + n); go r (n - 1) }\nmain = do { r <- IORef.newIORef 0; go r 5; v <- IORef.readIORef r; return v }"))
  (list "IO" 15))

(hk-test
  "newIORef inside a function passed via parameter"
  (hk-deep-force
    (hk-run
      "import qualified Data.IORef as IORef\nbump r = IORef.modifyIORef r (\\x -> x + 100)\nmain = do { r <- IORef.newIORef 1; bump r; v <- IORef.readIORef r; return v }"))
  (list "IO" 101))
