1 | # Copyright 2003 Dave Abrahams |
---|
2 | # Copyright 2002, 2003 Rene Rivera |
---|
3 | # Copyright 2002, 2003, 2004 Vladimir Prus |
---|
4 | # Distributed under the Boost Software License, Version 1.0. |
---|
5 | # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
---|
6 | |
---|
7 | # Various container classes. |
---|
8 | |
---|
9 | import "class" : * ; |
---|
10 | |
---|
11 | # Base for container objects. This lets us construct recursive structures. |
---|
12 | # That is containers with containers in them, specifically so we can tell |
---|
13 | # literal values from node values. |
---|
14 | # |
---|
15 | class node |
---|
16 | { |
---|
17 | rule __init__ ( |
---|
18 | value ? # Optional value to set node to initially. |
---|
19 | ) |
---|
20 | { |
---|
21 | self.value = $(value) ; |
---|
22 | } |
---|
23 | |
---|
24 | # Set the value of this node, passing nothing will clear it. |
---|
25 | # |
---|
26 | rule set ( value * ) |
---|
27 | { |
---|
28 | self.value = $(value) ; |
---|
29 | } |
---|
30 | |
---|
31 | # Get the value of this node. |
---|
32 | # |
---|
33 | rule get ( ) |
---|
34 | { |
---|
35 | return $(self.value) ; |
---|
36 | } |
---|
37 | } |
---|
38 | |
---|
39 | |
---|
40 | # A simple vector. Interface mimics the C++ std::vector and std::list, |
---|
41 | # with the exception that indices are one (1) based to follow Jam standard. |
---|
42 | # |
---|
43 | # TODO: Possibly add assertion checks. |
---|
44 | # |
---|
45 | class vector : node |
---|
46 | { |
---|
47 | import numbers : range ; |
---|
48 | import utility ; |
---|
49 | import sequence ; |
---|
50 | |
---|
51 | rule __init__ ( |
---|
52 | values * # Initial contents of vector. |
---|
53 | ) |
---|
54 | { |
---|
55 | node.__init__ ; |
---|
56 | self.value = $(values) ; |
---|
57 | } |
---|
58 | |
---|
59 | # Get the value of the first element. |
---|
60 | # |
---|
61 | rule front ( ) |
---|
62 | { |
---|
63 | return $(self.value[1]) ; |
---|
64 | } |
---|
65 | |
---|
66 | # Get the value of the last element. |
---|
67 | # |
---|
68 | rule back ( ) |
---|
69 | { |
---|
70 | return $(self.value[-1]) ; |
---|
71 | } |
---|
72 | |
---|
73 | # Get the value of the element at the given index, one based. |
---|
74 | # Access to elements of recursive structures is supported directly. |
---|
75 | # Specifying additional index values recursively accesses the elements as |
---|
76 | # containers. For example: [ $(v).at 1 : 2 ] would retrieve the second element |
---|
77 | # of our first element. This assuming the first element is a container. |
---|
78 | # |
---|
79 | rule at ( |
---|
80 | index # The element index, one based. |
---|
81 | : * # Additional indices to access recursively. |
---|
82 | ) |
---|
83 | { |
---|
84 | local r = $(self.value[$(index)]) ; |
---|
85 | if $(2) |
---|
86 | { |
---|
87 | r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ; |
---|
88 | } |
---|
89 | return $(r) ; |
---|
90 | } |
---|
91 | |
---|
92 | # Get the value contained in the given element. This has the same |
---|
93 | # functionality and interface as "at" but in addition gets the value |
---|
94 | # of the referenced element, assuming it's a "node". |
---|
95 | # |
---|
96 | rule get-at ( |
---|
97 | index # The element index, one based. |
---|
98 | : * # Additional indices to access recursively. |
---|
99 | ) |
---|
100 | { |
---|
101 | local r = $(self.value[$(index)]) ; |
---|
102 | if $(2) |
---|
103 | { |
---|
104 | r = [ $(r).at $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ; |
---|
105 | } |
---|
106 | return [ $(r).get ] ; |
---|
107 | } |
---|
108 | |
---|
109 | # Insert the given value into the front of the vector pushing the |
---|
110 | # rest of the elements back. |
---|
111 | # |
---|
112 | rule push-front ( |
---|
113 | value # Value to become first element. |
---|
114 | ) |
---|
115 | { |
---|
116 | self.value = $(value) $(self.value) ; |
---|
117 | } |
---|
118 | |
---|
119 | # Remove the front element from the vector. Does not return the value. |
---|
120 | # No effect if vector is empty. |
---|
121 | # |
---|
122 | rule pop-front ( ) |
---|
123 | { |
---|
124 | self.value = $(self.value[2-]) ; |
---|
125 | } |
---|
126 | |
---|
127 | # Add the given value at the end of the vector. |
---|
128 | # |
---|
129 | rule push-back ( |
---|
130 | value # Value to become back element. |
---|
131 | ) |
---|
132 | { |
---|
133 | self.value += $(value) ; |
---|
134 | } |
---|
135 | |
---|
136 | # Remove the back element from the vector. Does not return the value. |
---|
137 | # No effect if vector is empty. |
---|
138 | # |
---|
139 | rule pop-back ( ) |
---|
140 | { |
---|
141 | self.value = $(self.value[1--2]) ; |
---|
142 | } |
---|
143 | |
---|
144 | # Insert the given value at the given index, one based. The values |
---|
145 | # at and to the right of the of the index are push back to make room |
---|
146 | # for the new value. |
---|
147 | # |
---|
148 | rule insert ( |
---|
149 | index # The index to insert at, one based. |
---|
150 | : value # The value to insert. |
---|
151 | ) |
---|
152 | { |
---|
153 | local left = $(self.value[1-$(index)]) ; |
---|
154 | left = $(left[1--2]) ; |
---|
155 | local right = $(self.value[$(index)-]) ; |
---|
156 | self.value = $(left) $(value) $(right) ; |
---|
157 | } |
---|
158 | |
---|
159 | # Remove one or more elements from the vector. The range is inclusive, |
---|
160 | # and not specifying an end is equivalent to the [start,start] range. |
---|
161 | # |
---|
162 | rule erase ( |
---|
163 | start # Index of first element ro remove. |
---|
164 | end ? # Optional, index of last element to remove. |
---|
165 | ) |
---|
166 | { |
---|
167 | end ?= $(start) ; |
---|
168 | local left = $(self.value[1-$(start)]) ; |
---|
169 | left = $(left[1--2]) ; |
---|
170 | local right = $(self.value[$(end)-]) ; |
---|
171 | right = $(right[2-]) ; |
---|
172 | self.value = $(left) $(right) ; |
---|
173 | } |
---|
174 | |
---|
175 | # Remove all elements from the vector. |
---|
176 | # |
---|
177 | rule clear ( ) |
---|
178 | { |
---|
179 | self.value = ; |
---|
180 | } |
---|
181 | |
---|
182 | # The number of elements in the vector. |
---|
183 | # |
---|
184 | rule size ( ) |
---|
185 | { |
---|
186 | return [ sequence.length $(self.value) ] ; |
---|
187 | } |
---|
188 | |
---|
189 | # Returns "true" if there are NO elements in the vector, empty |
---|
190 | # otherwise. |
---|
191 | # |
---|
192 | rule empty ( ) |
---|
193 | { |
---|
194 | if ! $(self.value) |
---|
195 | { |
---|
196 | return true ; |
---|
197 | } |
---|
198 | } |
---|
199 | |
---|
200 | # Returns the list of all valid indices for this vector. |
---|
201 | rule indices ( ) |
---|
202 | { |
---|
203 | if ! [ empty ] |
---|
204 | { |
---|
205 | local size = [ size ] ; |
---|
206 | return [ range 1 : $(size) ] $(size) ; |
---|
207 | } |
---|
208 | } |
---|
209 | |
---|
210 | # Returns the textual representation of content. |
---|
211 | rule str ( ) |
---|
212 | { |
---|
213 | return "[" [ sequence.transform utility.str : $(self.value) ] "]" ; |
---|
214 | } |
---|
215 | |
---|
216 | # Sorts the vector inplace, calling 'utility.less' for |
---|
217 | # comparisons. |
---|
218 | # NOTE: this rule is unused at the moment. |
---|
219 | rule sort ( ) |
---|
220 | { |
---|
221 | self.value = |
---|
222 | [ sequence.insertion-sort $(self.value) : utility.less ] ; |
---|
223 | } |
---|
224 | |
---|
225 | # Returns true if content is equal to the content of other vector. |
---|
226 | # Uses 'utility.equal' for comparison. |
---|
227 | rule equal ( another ) |
---|
228 | { |
---|
229 | local mismatch ; |
---|
230 | if [ size ] = [ $(another).size ] |
---|
231 | { |
---|
232 | for local i in [ indices ] |
---|
233 | { |
---|
234 | if ! [ utility.equal [ at $(i) ] [ $(another).at $(i) ] ] |
---|
235 | { |
---|
236 | mismatch = true ; |
---|
237 | } |
---|
238 | } |
---|
239 | } |
---|
240 | else |
---|
241 | { |
---|
242 | mismatch = true ; |
---|
243 | } |
---|
244 | |
---|
245 | if ! $(mismatch) |
---|
246 | { |
---|
247 | return true ; |
---|
248 | } |
---|
249 | } |
---|
250 | } |
---|
251 | |
---|
252 | local rule __test__ ( ) |
---|
253 | { |
---|
254 | import assert ; |
---|
255 | import "class" : new ; |
---|
256 | |
---|
257 | local l = [ new vector ] ; |
---|
258 | assert.result 0 : $(l).size ; |
---|
259 | assert.result : $(l).indices ; |
---|
260 | assert.result "[" "]" : $(l).str ; |
---|
261 | $(l).push-back b ; |
---|
262 | $(l).push-front a ; |
---|
263 | assert.result 1 2 : $(l).indices ; |
---|
264 | assert.result "[" a b "]" : $(l).str ; |
---|
265 | assert.result a : $(l).front ; |
---|
266 | assert.result b : $(l).back ; |
---|
267 | $(l).insert 2 : d ; |
---|
268 | $(l).insert 2 : c ; |
---|
269 | $(l).insert 4 : f ; |
---|
270 | $(l).insert 4 : e ; |
---|
271 | $(l).pop-back ; |
---|
272 | assert.result 5 : $(l).size ; |
---|
273 | assert.result d : $(l).at 3 ; |
---|
274 | $(l).pop-front ; |
---|
275 | assert.result c : $(l).front ; |
---|
276 | assert.false $(l).empty ; |
---|
277 | $(l).erase 3 4 ; |
---|
278 | assert.result 2 : $(l).size ; |
---|
279 | |
---|
280 | local l2 = [ new vector q w e r t y ] ; |
---|
281 | assert.result 6 : $(l2).size ; |
---|
282 | $(l).push-back $(l2) ; |
---|
283 | assert.result 3 : $(l).size ; |
---|
284 | local l2-alias = [ $(l).back ] ; |
---|
285 | assert.result e : $(l2-alias).at 3 ; |
---|
286 | $(l).clear ; |
---|
287 | assert.true $(l).empty ; |
---|
288 | assert.false $(l2-alias).empty ; |
---|
289 | $(l2).pop-back ; |
---|
290 | assert.result t : $(l2-alias).back ; |
---|
291 | |
---|
292 | local l3 = [ new vector ] ; |
---|
293 | $(l3).push-back [ new vector 1 2 3 4 5 ] ; |
---|
294 | $(l3).push-back [ new vector a b c ] ; |
---|
295 | assert.result "[" "[" 1 2 3 4 5 "]" "[" a b c "]" "]" : $(l3).str ; |
---|
296 | $(l3).push-back [ new vector [ new vector x y z ] [ new vector 7 8 9 ] ] ; |
---|
297 | assert.result 1 : $(l3).at 1 : 1 ; |
---|
298 | assert.result b : $(l3).at 2 : 2 ; |
---|
299 | assert.result a b c : $(l3).get-at 2 ; |
---|
300 | assert.result 7 8 9 : $(l3).get-at 3 : 2 ; |
---|
301 | |
---|
302 | local l4 = [ new vector 4 3 6 ] ; |
---|
303 | $(l4).sort ; |
---|
304 | assert.result 3 4 6 : $(l4).get ; |
---|
305 | |
---|
306 | assert.false $(l4).equal $(l3) ; |
---|
307 | local l5 = [ new vector 3 4 6 ] ; |
---|
308 | assert.true $(l4).equal $(l5) ; |
---|
309 | # Check that vectors of different sizes are considered non-equal |
---|
310 | $(l5).pop-back ; |
---|
311 | assert.false $(l4).equal $(l5) ; |
---|
312 | local l6 = [ new vector [ new vector 1 2 3 ] ] ; |
---|
313 | assert.true $(l6).equal [ new vector [ new vector 1 2 3 ] ] ; |
---|
314 | } |
---|