;;; copy-flic.scm -- general copy functions for flic structures ;;; ;;; author : Sandra Loosemore ;;; date : 23 Feb 1993 ;;; ;;; ;;; The var-renamings argument is an a-list. It's used to map local vars ;;; in the input expression to new, gensymed vars. (define-flic-walker copy-flic (object var-renamings)) (define (copy-flic-list objects var-renamings) (let ((result '())) (dolist (o objects) (push (copy-flic o var-renamings) result)) (nreverse result))) (define (copy-flic-top object) (copy-flic object '())) (define-copy-flic flic-lambda (object var-renamings) (let ((new-vars (map (lambda (v) (let ((new (copy-temp-var (def-name v)))) (push (cons v new) var-renamings) (when (var-force-strict? v) (setf (var-force-strict? new) '#t)) (init-flic-var new '#f '#f))) (flic-lambda-vars object)))) (make-flic-lambda new-vars (copy-flic (flic-lambda-body object) var-renamings)))) ;;; Hack to avoid concatenating multiple gensym suffixes. (define (copy-temp-var sym) (if (gensym? sym) (let* ((string (symbol->string sym)) (n (string-length string)) (root (find-string-prefix string 0 n))) (create-temp-var root)) (create-temp-var sym))) (define (find-string-prefix string i n) (declare (type string string) (type fixnum i n)) (cond ((eqv? i n) string) ((char-numeric? (string-ref string i)) (substring string 0 i)) (else (find-string-prefix string (+ i 1) n)))) (define-copy-flic flic-let (object var-renamings) (let ((new-vars (map (lambda (v) (let ((new (copy-temp-var (def-name v)))) (when (var-force-inline? v) (setf (var-force-inline? new) '#t)) (push (cons v new) var-renamings) new)) (flic-let-bindings object)))) (for-each (lambda (new old) (init-flic-var new (copy-flic (var-value old) var-renamings) '#f)) new-vars (flic-let-bindings object)) (make-flic-let new-vars (copy-flic (flic-let-body object) var-renamings) (flic-let-recursive? object)))) (define-copy-flic flic-app (object var-renamings) (make-flic-app (copy-flic (flic-app-fn object) var-renamings) (copy-flic-list (flic-app-args object) var-renamings) (flic-app-saturated? object))) (define-copy-flic flic-ref (object var-renamings) (let* ((var (flic-ref-var object)) (entry (assq var var-renamings))) (if entry (make-flic-ref (cdr entry)) (make-flic-ref var)))) ; don't share structure (define-copy-flic flic-const (object var-renamings) (declare (ignore var-renamings)) (make-flic-const (flic-const-value object))) ; don't share structure (define-copy-flic flic-pack (object var-renamings) (declare (ignore var-renamings)) (make-flic-pack (flic-pack-con object))) ; don't share structure ;;; Don't have to gensym new block names; these constructs always ;;; happen in pairs. (define-copy-flic flic-case-block (object var-renamings) (make-flic-case-block (flic-case-block-block-name object) (copy-flic-list (flic-case-block-exps object) var-renamings))) (define-copy-flic flic-return-from (object var-renamings) (make-flic-return-from (flic-return-from-block-name object) (copy-flic (flic-return-from-exp object) var-renamings))) (define-copy-flic flic-and (object var-renamings) (make-flic-and (copy-flic-list (flic-and-exps object) var-renamings))) (define-copy-flic flic-if (object var-renamings) (make-flic-if (copy-flic (flic-if-test-exp object) var-renamings) (copy-flic (flic-if-then-exp object) var-renamings) (copy-flic (flic-if-else-exp object) var-renamings))) (define-copy-flic flic-sel (object var-renamings) (make-flic-sel (flic-sel-con object) (flic-sel-i object) (copy-flic (flic-sel-exp object) var-renamings))) (define-copy-flic flic-is-constructor (object var-renamings) (make-flic-is-constructor (flic-is-constructor-con object) (copy-flic (flic-is-constructor-exp object) var-renamings))) (define-copy-flic flic-con-number (object var-renamings) (make-flic-con-number (flic-con-number-type object) (copy-flic (flic-con-number-exp object) var-renamings))) (define-copy-flic flic-void (object var-renamings) (declare (ignore object var-renamings)) (make-flic-void)) ; don't share structure