(define (make-graph-walker make-queue
			   add-to-queue
			   remove-from-queue)
  (lambda (node node-filter)
    (let ((queue (make-queue)))

      (define (per-node node count)
	(let ((count (+ count 1)))
	  (for-each
	   (lambda (link)
	     (add-to-queue link
			   (link-priority link)
			   queue))
	   (node-links node))
	  (maybe-accumulate
	   node
	   count
	   (lambda () (next-node count)))))

      (define (next-node count)
	(let ((link (remove-from-queue queue)))
	  (if link
	      (let ((node
		     (dereference-link
		      link
		      node-filter)))
		(if node
		    (per-node node count)
		    (next-node count)))
	      (cons #f count))))

      (per-node node 0))))

(define (maybe-accumulate node count get-next)
  (if *debug-trace?*
      (begin
	(fresh-line)
	(write-string ";trace: ")
	(write (node-name node))
	(newline)))
  (if (node-value node)
      (cons (cons node get-next) count)
      (get-next)))

(define (make-graph-walker make-queue
			   add-to-queue
			   remove-from-queue)
  (lambda (node node-filter)

    (define (per-node node queue)
      (let ((queue
	     (enqueue (node-links node) queue)))
	(maybe-accumulate
	 node
	 (lambda () (next-node queue)))))

    (define (enqueue links queue)
      (if (pair? links)
	  (enqueue
	   (cdr links)
	   (add-to-queue (car links)
			 (link-priority (car links))
			 queue))
	  queue))

    (define (next-node queue)
      (receive (link queue)
	  (remove-from-queue queue)
	(if link
	    (let ((node
		   (dereference-link
		    link
		    node-filter)))
	      (if node
		  (per-node node queue)
		  (next-node queue)))
	    #f)))

    (per-node node (make-queue))))