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