git.fiddlerwoaroof.com
Raw Blame History
;;; This file handles common subexpressions in the interface file.
;;; Common subexpressions are detected in two places: gtypes and strictness
;;; properties.

;;; Compressing strictness signatures

;;; A strictness is represented by a list of booleans.  We do two things to
;;; compress strictnesses: all lists less than *pre-defined-strictness-size*
;;; are pre-computed in a vector and the first *pre-defined-strictness-vars*
;;; vector elements are cached in global vars.  The strictness will dump as
;;; as either a global or as a vector reference into the vector.

(define (initialize-strictness-table)
  (setf (dynamic *pre-defined-strictness-table*)
	(make-vector (expt 2 (1+ (dynamic *pre-defined-strictness-size*)))))
  (setf (vector-ref *pre-defined-strictness-table* 1) '())
  (do ((i 1 (1+ i))
       (j 1 (* j 2))
       (k 2 (* k 2)))
      ((> i *pre-defined-strictness-size*))
    (do ((l 0 (1+ l)))
	((>= l j))
      (setf (vector-ref *pre-defined-strictness-table* (+ k l))
	    (cons '#f (vector-ref *pre-defined-strictness-table* (+ j l))))
      (setf (vector-ref *pre-defined-strictness-table* (+ k j l))
	    (cons '#t (vector-ref *pre-defined-strictness-table* (+ j l))))))
  (set-strictness-vars))

(define (strictness-table-ref x)
  (vector-ref (dynamic *pre-defined-strictness-table*) x))

(define (dump-strictness s)
  (if (null? s)
      ''()
      (dump-strictness-1 s s 0 0)))

(define (dump-strictness-1 s s1 n size)
  (if (null? s1)
      (if (> size *pre-defined-strictness-size*)
	  (dump-big-strictness (- size *pre-defined-strictness-size*) s)
	  (let ((k (+ n (expt 2 size))))
	    (if (< k *pre-defined-strictness-vars*)
		`(dynamic ,(vector-ref *pre-defined-strictness-names* k))
		`(strictness-table-ref ,k))))
      (dump-strictness-1 s (cdr s1) (+ (* 2 n) (if (car s1) 1 0)) (1+ size))))

(define (dump-big-strictness k s)
  (if (= k 0)
      (dump-strictness s)
      `(cons ',(car s)
	     ,(dump-big-strictness (1- k) (cdr s)))))

;;; This routine handles saving type signatures (gtypes).  
;;; common subexpressions are detected in two places: the type body
;;; and the the contexts.

(define (init-predefined-gtyvars)
  (setf *saved-gtyvars* (make-vector *num-saved-gtyvars*))
  (dotimes (i *num-saved-gtyvars*)
     (setf (vector-ref *saved-gtyvars* i) (**gtyvar i)))
  (setup-gtyvar-vars))

(define (init-cse-structs)
  (initialize-strictness-table)
  (init-predefined-gtyvars))

(define (save-cse-value v)
  (setf (vector-ref (dynamic *saved-cse-values*) (dynamic *cse-value-num*)) v)
  (incf (dynamic *cse-value-num*)))

(define (cse-init-code)
  (let* ((n (length *cse-objects*))
	 (init-code '()))
    (do ((i (1- n) (1- i))
	 (init *cse-objects* (cdr init)))
	((null? init))
      (push `(save-cse-value ,(car init)) init-code))
    `((setf *saved-cse-values* (make-vector ,n))
      (setf *cse-value-num* 0)
      ,@init-code)))

(define (remember-dumped-object init-code)
  (push init-code *cse-objects*)
  (incf *cse-object-num*)
  *cse-object-num*)

(define (cse-value-ref x)
  (vector-ref (dynamic *saved-cse-values*) x))

(define (cse-ref-code n)
  (cond ((eqv? n 0)
	 ''())
	((<= n *num-saved-gtyvars*)
	 `(dynamic ,(vector-ref *saved-gtyvar-varnames* (1- n))))
	(else
	 `(cse-value-ref ,(- n *num-saved-gtyvars* 1)))))

(define (dump-gtyvar g)
  (let ((n (gtyvar-varnum g)))
    (if (< n *num-saved-gtyvars*)
	(1+ n)
	(remember-dumped-object `(**gtyvar ,n)))))

(define (dump-context-list contexts)
  (if (null? contexts)
      0
      (let* ((rest (dump-context-list (cdr contexts)))
	     (classes (dump-class-list (car contexts)))
	     (t1 (assq/insert-l classes *gtype-class-index*))
	     (res (assq/insert rest (cdr t1))))
	  (if (eq? (cdr res) '#f)
	      (let ((z (remember-dumped-object
			`(cons ,(cse-ref-code classes) ,(cse-ref-code rest)))))
		(setf (cdr res) z)
		z)
	      (cdr res)))))

(define (dump-class-list classes)
  (if (null? classes)
      0
      (let* ((rest (dump-class-list (cdr classes)))
	     (class (dump-class/n (car classes)))
	     (t1 (assq/insert-l class *context-class-index*))
	     (res (assq/insert rest (cdr t1))))
	  (if (eq? (cdr res) '#f)
	      (let ((z (remember-dumped-object
			`(cons ,class ,(cse-ref-code rest)))))
		(setf (cdr res) z)
		z)
	      (cdr res)))))
	
(define (dump-gtype-1 g)
  (cond ((gtyvar? g)
	 (dump-gtyvar g))
	((ntyvar? g)
	 (dump-gtype-1 (prune g)))
	(else
	 (dump-gtycon g))))

(define (dump-gtycon g)
  (let* ((ty (ntycon-tycon g))
	 (tycon (if (algdata? ty) (dump-algdata/n ty) (dump-synonym/n ty)))
	 (l (dump-gtype-list (ntycon-args g)))
	 (t1 (assq/insert-l tycon *gtype-tycon-index*))
	 (res (assq/insert l (cdr t1))))
    (if (eq? (cdr res) '#f)
	(let ((z (remember-dumped-object
		  `(**ntycon ,tycon ,(cse-ref-code l)))))
	  (setf (cdr res) z)
	  z)
	(cdr res))))

(define (dump-gtype-list l)
  (if (null? l)
      0
      (let* ((g (dump-gtype-1 (car l)))
	     (rest (dump-gtype-list (cdr l)))
	     (t1 (assq/insert-l g *gtype-list-index*))
	     (res (assq/insert rest (cdr t1))))
	(if (eq? (cdr res) '#f)
	    (let ((z (remember-dumped-object
		      `(cons ,(cse-ref-code g)
			     ,(cse-ref-code rest)))))
	      (setf (cdr res) z)
	      z)
	    (cdr res)))))

(define (dump-gtype/cse g)
 (cse-ref-code
  (let* ((context (dump-context-list (gtype-context g)))
	 (type (dump-gtype-1 (gtype-type g)))
	 (t1 (assq/insert-l type *gtype-index*))
	 (res (assq/insert context (cdr t1))))
    (if (eq? (cdr res) '#f)
	(let ((z (remember-dumped-object
		      `(**gtype ,(cse-ref-code context)
				,(cse-ref-code type)))))
	      (setf (cdr res) z)
	      z)
	(cdr res)))))