; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.

(define (ensure-instantiated package phase visit? invoke?)
  (let ((post
	 (cond
	  ((not (package-visit-template package))
	   (compile-package package) ; #### should make sure to do this only in the original package
	   (lambda ()
	     ;; do this lazily?
	     (freeze-template! (package-visit-template package) package)
	     (freeze-template! (package-invoke-template package) package)))
	  (visit?
	   (visit-package package phase)
	   values)
	  (else values))))
    (set-package-visited?! package #t)
    (if (or invoke?
	    (positive? phase))
	(begin
	  (invoke-package package phase)	; benefit from cheap linking
	  (set-package-invoked?! package #t)))
    (post)))

(define (ensure-loaded . structs)
  (force-output (current-output-port))		; avoid interleaved output
  (let ((out (current-noise-port)))
    (for-each (lambda (package+phase)
		(display #\[ out)
		(let ((package (car package+phase))
		      (phase (cdr package+phase)))
		  (display (package-name package) out)
		  (ensure-instantiated package phase #t #t))
		(display #\] out)
		(newline out))
	      (collect-packages structs
				0
				(lambda (package phase)
				  (or (not (package-visit-template package))
				      (not (package-visited? package))
				      (not (package-invoked? package))))
				(lambda (struct phase) #t)))))

(define (invoke-package package phase)
  (invoke-package-template package package 
			   phase
			   (package-invoke-template package)))

(define (visit-package package phase)
  (invoke-package-template package 
			   (comp-env-next-phase (package->environment package))
			   phase
			   (package-visit-template package)))

(define (invoke-package-template package env phase template)
  (with-interaction-environment 
   package
   (lambda ()
     (invoke-closure
      (make-closure
       ;; #t means warn about undefined variables
       (link template env phase #t)
       (package-uid package))))))
