;; R7RS module system tests — define-library / import

(defsuite
  "define-library-basic"
  (deftest
    "define and import a library"
    (define-library
      (test math)
      (export add square)
      (begin
        (define add (fn (a b) (+ a b)))
        (define square (fn (x) (* x x)))))
    (import (test math))
    (assert= (add 3 4) 7)
    (assert= (square 5) 25))
  (deftest
    "library isolation — internal not exported"
    (define-library
      (test internal)
      (export public-fn)
      (begin
        (define helper (fn (x) (* x 2)))
        (define public-fn (fn (x) (helper (+ x 1))))))
    (import (test internal))
    (assert= (public-fn 5) 12))
  (deftest
    "multiple libraries"
    (define-library
      (test greet)
      (export greet)
      (begin (define greet (fn (name) (str "Hello, " name "!")))))
    (define-library
      (test format)
      (export shout)
      (begin (define shout (fn (s) (upper s)))))
    (import (test greet))
    (import (test format))
    (assert= (greet "world") "Hello, world!")
    (assert= (shout "hello") "HELLO")))

(defsuite
  "import-qualifiers"
  (deftest
    "import with only"
    (define-library
      (test utils)
      (export inc dec double)
      (begin
        (define inc (fn (x) (+ x 1)))
        (define dec (fn (x) (- x 1)))
        (define double (fn (x) (* x 2)))))
    (import (only (test utils) inc double))
    (assert= (inc 5) 6)
    (assert= (double 5) 10))
  (deftest
    "import with prefix"
    (define-library
      (test prefixed)
      (export value)
      (begin (define value 42)))
    (import (prefix (test prefixed) tp:))
    (assert= tp:value 42)))

(defsuite
  "library-registry"
  (deftest
    "library-loaded? returns true after define"
    (define-library (test check) (export x) (begin (define x 1)))
    (assert (library-loaded? (quote (test check)))))
  (deftest
    "library-loaded? returns false for unknown"
    (assert (not (library-loaded? (quote (nonexistent lib)))))))

(defsuite
  "import-suspension"
  (deftest
    "import of unknown library suspends"
    (let
      ((state (cek-step-loop (make-cek-state (quote (import (remote data))) (make-env) (list)))))
      (assert (cek-suspended? state))
      (assert= (get (cek-io-request state) "op") "import")))
  (deftest
    "import suspension resumes after library registered"
    (let
      ((state (cek-step-loop (make-cek-state (quote (begin (import (lazy lib)) (get-value))) (make-env) (list)))))
      (assert (cek-suspended? state))
      (register-library (quote (lazy lib)) {:get-value (fn () 42)})
      (let
        ((final (cek-resume state nil)))
        (assert (cek-terminal? final))
        (assert= (cek-value final) 42)))))