| 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 | } |
|---|