;; lib/minikanren/project.sx — Phase 5 piece B: `project`.
;;
;;   (project (x y) g1 g2 ...)
;;     — rebinds each named var to (mk-walk* var s) within the body's
;;       lexical scope, then runs the conjunction of the body goals on
;;       the same substitution. Use to escape into regular SX (arithmetic,
;;       string ops, host predicates) when you need a ground value.
;;
;; If any of the projected vars is still unbound at this point, the body
;; sees the raw `(:var NAME)` term — that is intentional and lets you
;; mix project with `(== ground? var)` patterns or with conda guards.
;;
;; Hygiene: substitution parameter is gensym'd so it doesn't capture user
;; vars (`s` is a popular relation parameter name).

(defmacro
  project
  (vars &rest goals)
  (let
    ((s-sym (gensym "proj-s-")))
    (quasiquote
      (fn
        ((unquote s-sym))
        ((let (unquote (map (fn (v) (list v (list (quote mk-walk*) v s-sym))) vars)) (mk-conj (splice-unquote goals)))
          (unquote s-sym))))))
