File: vector.scm

package info (click to toggle)
scheme48 1.8%2Bdfsg-1%2Bdeb7u1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 14,984 kB
file content (212 lines) | stat: -rw-r--r-- 6,593 bytes parent folder | download | duplicates (4)
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))