;; lib/minikanren/fresh.sx — Phase 2 piece B: `fresh` for introducing
;; logic variables inside a goal body.
;;
;;   (fresh (x y z) goal1 goal2 ...)
;;     ≡ (let ((x (make-var)) (y (make-var)) (z (make-var)))
;;         (mk-conj goal1 goal2 ...))
;;
;; A macro rather than a function so user-named vars are real lexical
;; bindings — which is also what miniKanren convention expects.
;; The empty-vars form (fresh () goal ...) is just a goal grouping.

(defmacro
  fresh
  (vars &rest goals)
  (quasiquote
    (let
      (unquote (map (fn (v) (list v (list (quote make-var)))) vars))
      (mk-conj (splice-unquote goals)))))

;; call-fresh — functional alternative for code that builds goals
;; programmatically:
;;   ((call-fresh (fn (x) (== x 7))) empty-s) → ({:_.N 7})
(define call-fresh (fn (f) (fn (s) ((f (make-var)) s))))
