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

; Table for mapping name+phase to value.  The only constraint is that
; the value may not be a table.

; We use a two-level table: A name maps either to the value directly
; for phase 0 (very common), or to a table mapping phases to values.

; (Using a table directlry mapping name/phase pairs to values
; drastically affects performance.)

(define (make-name+phase-table)
  (make-symbol-table))

; returns value and token; token can be passed to name+phase-table-set!
(define (name+phase-table-ref table name phase)
  (cond
   ((table-ref table name)
    => (lambda (entry)
	 (cond
	  ((table? entry)
	   (values (table-ref entry phase) entry))
	  ((zero? phase)
	   (values entry entry))
	  (else (values #f entry)))))
   (else (values #f #f))))

(define (name+phase-table-set! table name phase token new-val)
  (let ((entry
	 (or token
	     (receive (_ entry) (name+phase-table-ref table name phase)
	       entry))))
    (cond
     ((table? entry)
      (table-set! entry phase new-val))
     (entry
      (let ((phase-table (make-integer-table)))
	(table-set! phase-table 0 entry)
	(table-set! phase-table phase new-val)
	(table-set! table name phase-table)))
     ((zero? phase)
      (table-set! table name new-val))
     (else
      (let ((phase-table (make-integer-table)))
	(table-set! phase-table phase new-val)
	(table-set! table name phase-table))))))

(define (name+phase-table-walk proc table)
  (table-walk (lambda (name entry)
		(if (table? entry)
		    (table-walk (lambda (phase val)
				  (proc name phase val))
				entry)
		    (proc name 0 entry)))
	      table))

(define (name+phase-table-walk-phases proc table name)
  (cond
   ((table-ref table name)
    => (lambda (entry)
	 (if (table? entry)
	     (table-walk (lambda (phase val)
			   (proc phase val))
			 entry)
	     (proc 0 entry))))))


(define (make-name+phase-table-immutable! table)
  (table-walk (lambda (name entry)
		(if (table? entry)
		    (make-table-immutable! entry)))
	      table)
  (make-table-immutable! table))
