;; lib/scheme/tests/modules.sx — define-library + import.

(define scm-mod-pass 0)
(define scm-mod-fail 0)
(define scm-mod-fails (list))

(define
  scm-mod-test
  (fn
    (name actual expected)
    (if
      (= actual expected)
      (set! scm-mod-pass (+ scm-mod-pass 1))
      (begin
        (set! scm-mod-fail (+ scm-mod-fail 1))
        (append! scm-mod-fails {:name name :actual actual :expected expected})))))

(define
  scm-mod
  (fn
    (src)
    (scheme-eval-program (scheme-parse-all src) (scheme-standard-env))))

;; ── Basic define-library + import ───────────────────────────────

(scm-mod-test
  "simple lib: sq exported"
  (scm-mod
    "(define-library (my math)\n       (export sq)\n       (begin (define (sq x) (* x x))))\n     (import (my math))\n     (sq 5)")
  25)
(scm-mod-test
  "lib: multiple exports"
  (scm-mod
    "(define-library (my math)\n       (export sq cube)\n       (begin\n         (define (sq x) (* x x))\n         (define (cube x) (* x x x))))\n     (import (my math))\n     (list (sq 5) (cube 3))")
  (list 25 27))
(scm-mod-test
  "lib: single-symbol name"
  (scm-mod
    "(define-library (utils)\n       (export greet)\n       (begin (define (greet name) (string-append \"hi \" name))))\n     (import (utils))\n     (string=? (greet \"world\") \"hi world\")")
  true)

;; ── Unexported names are not visible ───────────────────────────

(scm-mod-test
  "lib: private name not exported"
  (scm-mod
    "(define-library (my math)\n       (export sq)\n       (begin\n         (define (sq x) (* x x))\n         (define (private-helper x) (+ x 1))))\n     (import (my math))\n     (guard (e (else 'unbound)) private-helper)")
  "unbound")

;; ── Library calls its own internals ─────────────────────────────

(scm-mod-test
  "lib: internal calls private fn"
  (scm-mod
    "(define-library (my math)\n       (export public-add1)\n       (begin\n         (define (private-inc x) (+ x 1))\n         (define (public-add1 x) (private-inc x))))\n     (import (my math))\n     (public-add1 41)")
  42)

;; ── Two libs, both imported ────────────────────────────────────

(scm-mod-test
  "two libs: both imported"
  (scm-mod
    "(define-library (a) (export af) (begin (define (af) 1)))\n     (define-library (b) (export bf) (begin (define (bf) 2)))\n     (import (a) (b))\n     (+ (af) (bf))")
  3)

;; ── Unknown library import errors ──────────────────────────────

(scm-mod-test
  "import: unknown lib errors"
  (scm-mod "(guard (e (else 'unknown-lib)) (import (no such lib)))")
  "unknown-lib")

(define scm-mod-tests-run! (fn () {:total (+ scm-mod-pass scm-mod-fail) :passed scm-mod-pass :failed scm-mod-fail :fails scm-mod-fails}))
