1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
; Copyright (c) 1993-2008 by Richard Kelsey. See file COPYING.
;----------------------------------------------------------------------------
; STORING NODE TREES IN VECTORS
;----------------------------------------------------------------------------
; The use of OTHER and GLOBAL depends on whether NODE->VECTOR or VECTOR->NODE
(define-record-type vec
(vector ; an expanding vector (NODE->VECTOR) or just a vector (VECTOR->NODE)
(index) ; the index of the next empty slot or the next thing to read
locals ; vector of local variables (VECTOR->NODE only)
)
())
(define make-vec vec-maker)
; Add value as the next thing in the VEC.
(define (add-datum vec value)
(xvector-set! (vec-vector vec) (vec-index vec) value)
(set-vec-index! vec (+ 1 (vec-index vec))))
; Convert a node into a vector
;
; literal => QUOTE <literal> <rep>
; reference => <index of the variable's name in vector> if lexical, or
; GLOBAL <variable> if it isn't
; lambda => LAMBDA <stuff> #vars <variable names+reps> <call>
; call => CALL <source> <primop> <exits> <number of args> <args>
; Preserve the node as a vector.
(define (node->vector node)
(let ((vec (make-vec (make-xvector #f) 0 #f)))
(real-node->vector node vec)
(xvector->vector (vec-vector vec))))
; The main dispatch
(define (real-node->vector node vec)
(case (node-variant node)
((literal)
(literal->vector node vec))
((reference)
(reference->vector node vec))
((lambda)
(lambda->vector node vec))
((call)
(add-datum vec 'call)
(call->vector node vec))
(else
(bug "node->vector got funny node ~S" node))))
; VARIABLE-FLAGs are used to mark variables with their position in the
; vector.
(define (lambda->vector node vec)
(add-datum vec 'lambda)
(add-datum vec (lambda-name node))
(add-datum vec (lambda-type node))
(add-datum vec (lambda-protocol node))
(add-datum vec (lambda-source node))
(add-datum vec (lambda-variable-count node))
(for-each (lambda (var)
(cond ((not var)
(add-datum vec #f))
(else
(set-variable-flag! var (vec-index vec))
(add-datum vec (variable-name var))
(add-datum vec (variable-type var)))))
(lambda-variables node))
(call->vector (lambda-body node) vec)
(for-each (lambda (var)
(if var
(set-variable-flag! var #f)))
(lambda-variables node)))
; If VAR is bound locally, then put the index of the variable within the vector
; into the vector.
(define (reference->vector node vec)
(let ((var (reference-variable node)))
(cond ((not (variable-binder var))
(add-datum vec 'global)
(add-datum vec var))
((integer? (variable-flag var))
(add-datum vec (variable-flag var)))
(else
(bug "variable ~S has no vector location" var)))))
(define (literal->vector node vec)
(let ((value (literal-value node)))
(add-datum vec 'quote)
(add-datum vec (literal-value node))
(add-datum vec (literal-type node))))
; This counts down so that the continuation will be done after the arguments.
; Why does this matter?
(define (call->vector node vec)
(let* ((args (call-args node))
(len (vector-length args)))
(add-datum vec (call-source node))
(add-datum vec (call-primop node))
(add-datum vec (call-exits node))
(add-datum vec len)
(do ((i (- len 1) (- i 1)))
((< i 0))
(real-node->vector (vector-ref args i) vec))))
;----------------------------------------------------------------------------
; TURNING VECTORS BACK INTO NODES
;----------------------------------------------------------------------------
(define (vector->node vector)
(if (not (vector? vector))
(bug "VECTOR->NODE got funny value ~S~%" vector)
(let ((vec (make-vec vector -1 (make-vector (vector-length vector)))))
(real-vector->node vec))))
(define (vector->leaf-node vector)
(case (vector-ref vector 0)
((quote global)
(vector->node vector))
(else #f)))
; Pop the next thing off of the vector (which is really a (<vector> . <index>)
; pair).
(define (get-datum vec)
(let ((i (+ (vec-index vec) 1)))
(set-vec-index! vec i)
(vector-ref (vec-vector vec) i)))
; This prevents the (unecessary) resimplification of recreated nodes.
(define (real-vector->node vec)
(let ((node (totally-real-vector->node vec)))
(set-node-simplified?! node #t)
node))
; Dispatch on the next thing in VEC.
(define (totally-real-vector->node vec)
(let ((exp (get-datum vec)))
(cond ((integer? exp)
(make-reference-node (vector-ref (vec-locals vec) exp)))
(else
(case exp
((lambda)
(vector->lambda-node vec))
((quote)
(let* ((value (get-datum vec))
(rep (get-datum vec)))
(make-literal-node value rep)))
((global)
(make-reference-node (get-datum vec)))
((call)
(vector->call-node vec))
((import) ; global variable from a separate compilation
(make-reference-node (lookup-imported-variable (get-datum vec))))
(else
(no-op
(bug '"real-vector->node got an unknown code ~S" exp))))))))
(define (vector->lambda-node vec)
(let* ((name (get-datum vec))
(type (get-datum vec))
(protocol (get-datum vec))
(source (get-datum vec))
(count (get-datum vec))
(vars (do ((i 0 (+ i 1))
(v '() (cons (vector->variable vec) v)))
((>= i count) v)))
(node (make-lambda-node name type (reverse! vars))))
(set-lambda-protocol! node protocol)
(set-lambda-source! node source)
(attach-body node (vector->call-node vec))
(set-node-simplified?! (lambda-body node) #t)
node))
; Replace a variable name with a new variable.
(define (vector->variable vec)
(let ((name (get-datum vec)))
(if name
(let ((var (make-variable name (get-datum vec))))
(vector-set! (vec-locals vec) (+ -1 (vec-index vec)) var)
var)
#f)))
(define (vector->call-node vec)
(let* ((source (get-datum vec))
(primop (let ((p (get-datum vec)))
(if (primop? p)
p
(lookup-primop p))))
(exits (get-datum vec))
(count (get-datum vec))
(node (make-call-node primop count exits)))
(do ((i (- count 1) (- i 1)))
((< i 0))
(attach node i (real-vector->node vec)))
(set-call-source! node source)
node))
|