casty 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,841 @@
1
+ ######################################################################
2
+ #
3
+ # NodeList and subclasses.
4
+ #
5
+ ######################################################################
6
+
7
+ module C
8
+ # Declare all the classes, so we don't have to declare the
9
+ # inheritances later.
10
+ class NodeList < Node; abstract; end
11
+ class NodeArray < NodeList; end
12
+ class NodeChain < NodeList; end
13
+
14
+ #
15
+ # Abstract base class of the Node list classes.
16
+ #
17
+ class NodeList
18
+ def self.[](*args)
19
+ new.concat(args)
20
+ end
21
+
22
+ include Enumerable
23
+ def size
24
+ length
25
+ end
26
+
27
+ def ==(other)
28
+ return false if !other.is_a? C::NodeList
29
+
30
+ # none of the NodeList classes here have fields, but there's no
31
+ # reason why one can't subclass one to have fields
32
+ fields.each do |field|
33
+ mine = self .send(field.reader)
34
+ yours = other.send(field.reader)
35
+ mine == yours or return false
36
+ end
37
+
38
+ other = other.to_a
39
+ return false if other.length != self.length
40
+ each_with_index do |node, i|
41
+ return false if node != other[i]
42
+ end
43
+ return true
44
+ end
45
+
46
+ def hash
47
+ hash = 0
48
+ each do |node|
49
+ hash ^= node.hash
50
+ end
51
+ return hash
52
+ end
53
+
54
+ def to_s
55
+ self.join ', '
56
+ end
57
+
58
+ def inspect
59
+ "#{self.class}[#{self.join(', ')}]"
60
+ end
61
+
62
+ protected # -----------------------------------------------------
63
+
64
+ #
65
+ # Return `[i, n, splat?]', where if `args' is used as an index to
66
+ # ::Array#[]=, it is equivalent to calling:
67
+ #
68
+ # val = args.pop
69
+ # if splat?
70
+ # array[i, n] = *val
71
+ # else
72
+ # array[i, n] = val
73
+ # end
74
+ #
75
+ def parse_index(*args)
76
+ # what we must do:
77
+ #
78
+ # -- move numbers into range 0..length-1
79
+ # -- i..j --> i...j+1
80
+ # -- i...j --> i, j-i
81
+ case args.length
82
+ when 1
83
+ arg = args.first
84
+ if arg.is_a? ::Range
85
+ if arg.exclude_end?
86
+ i = wrap_index(arg.begin)
87
+ j = wrap_index(arg.begin)
88
+ return [i, j-1, true]
89
+ else
90
+ i = wrap_index(arg.begin)
91
+ j = wrap_index(arg.begin)
92
+ return [i, j+1-i, true]
93
+ end
94
+ else
95
+ i = wrap_index(arg)
96
+ return [i, 1, false]
97
+ end
98
+ when 2
99
+ return [args[0], args[1], true]
100
+ else
101
+ raise ArgumentError, "wrong number of arguments"
102
+ end
103
+ end
104
+
105
+ #
106
+ # Wrap the given index if less than 0, and return it.
107
+ #
108
+ def wrap_index(i)
109
+ i < 0 ? (i + length) : i
110
+ end
111
+
112
+ #
113
+ # Prepare the given nodes for addition. This means:
114
+ # -- clone any attached nodes as necessary
115
+ # -- set the nodes' parents to self.
116
+ #
117
+ # `oldnodes' are the nodes that will be replaced. These aren't
118
+ # cloned the first time they appear in `nodes'.
119
+ #
120
+ # Return the list of nodes to add.
121
+ #
122
+ def add_prep(nodes, oldnodes=nil)
123
+ if oldnodes
124
+ oldnodes = oldnodes.map{|n| n.object_id}
125
+ nodes.map! do |node|
126
+ if node.attached? && oldnodes.delete(node.object_id).nil?
127
+ node = node.clone
128
+ end
129
+ set_parent node, self
130
+ node
131
+ end
132
+ else
133
+ nodes.map! do |node|
134
+ node = node.clone if node.attached?
135
+ set_parent node, self
136
+ node
137
+ end
138
+ end
139
+ return nodes
140
+ end
141
+
142
+ #
143
+ # Set the parent of `node' to `val'.
144
+ #
145
+ def set_parent(node, val)
146
+ node.send(:parent=, val)
147
+ end
148
+ end
149
+
150
+ class NodeArray
151
+ def assert_invariants(testcase)
152
+ super
153
+ testcase.assert_same(::Array, @array)
154
+ @array.each_with_index do |node, i|
155
+ assert_same(i, node.instance_variable_get(:@parent_index))
156
+ end
157
+ end
158
+
159
+ def initialize
160
+ super
161
+ @array = []
162
+ end
163
+
164
+ def dup
165
+ ret = super
166
+ ret.instance_variable_set(:@array, [])
167
+ dupes = self.map{|n| n.dup}
168
+ return ret.push(*dupes)
169
+ end
170
+
171
+ def clone
172
+ ret = super
173
+ ret.instance_variable_set(:@array, [])
174
+ clones = self.map{|n| n.clone}
175
+ return ret.push(*clones)
176
+ end
177
+ end
178
+
179
+ class NodeChain
180
+ def assert_invariants(testcase)
181
+ super
182
+ assert_same(@length.zero?, @first.nil?)
183
+ assert_same(@length.zero?, @last.nil?)
184
+ unless @length.zero?
185
+ assert_same(@first, self[0])
186
+ assert_same(@last, self[@length-1])
187
+ (0...@length.times).each do |i|
188
+ nodeprev = self[i].instance_variable_get(:@prev)
189
+ nodenext = self[i].instance_variable_get(:@next)
190
+ if i == 0
191
+ assert_nil(nodeprev)
192
+ else
193
+ assert_same(self[i-1], nodeprev)
194
+ end
195
+
196
+ if i == @length-1
197
+ assert_nil(nodenext)
198
+ else
199
+ assert_same(self[i+1], nodenext)
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ def initialize
206
+ super
207
+ @first = nil
208
+ @last = nil
209
+ @length = 0
210
+ end
211
+
212
+ def dup
213
+ ret = super
214
+ ret.instance_variable_set(:@first, nil)
215
+ ret.instance_variable_set(:@last, nil)
216
+ ret.instance_variable_set(:@length, 0)
217
+ dupes = self.map{|n| n.dup}
218
+ ret.push(*dupes)
219
+ return ret
220
+ end
221
+
222
+ def clone
223
+ ret = super
224
+ ret.instance_variable_set(:@first, nil)
225
+ ret.instance_variable_set(:@last, nil)
226
+ ret.instance_variable_set(:@length, 0)
227
+ clones = self.map{|n| n.clone}
228
+ ret.push(*clones)
229
+ return ret
230
+ end
231
+ end
232
+
233
+ # ------------------------------------------------------------------
234
+ # Methods called from children
235
+ # ------------------------------------------------------------------
236
+
237
+ class NodeArray
238
+ def node_after(node)
239
+ node.parent.equal? self or
240
+ raise ArgumentError, "node is not a child"
241
+ @array[index = node.instance_variable_get(:@parent_index)+1]
242
+ end
243
+
244
+ def node_before(node)
245
+ node.parent.equal? self or
246
+ raise ArgumentError, "node is not a child"
247
+ index = node.instance_variable_get(:@parent_index)
248
+ if index.zero?
249
+ return nil
250
+ else
251
+ return @array[index-1]
252
+ end
253
+ end
254
+
255
+ def remove_node(node)
256
+ node.parent.equal? self or
257
+ raise ArgumentError, "node is not a child"
258
+ index = node.instance_variable_get(:@parent_index)
259
+ index.instance_variable_set(:@parent_index, nil)
260
+ removed_(@array[index])
261
+ @array.delete_at(index)
262
+ adjust_indices_(index)
263
+ return self
264
+ end
265
+
266
+ def insert_after(node, *newnodes)
267
+ node.parent.equal? self or
268
+ raise ArgumentError, "node is not a child"
269
+ index = node.instance_variable_get(:@parent_index) + 1
270
+ insert(index, *newnodes)
271
+ return self
272
+ end
273
+ def insert_before(node, *newnodes)
274
+ node.parent.equal? self or
275
+ raise ArgumentError, "node is not a child"
276
+ index = node.instance_variable_get(:@parent_index)
277
+ insert(index, *newnodes)
278
+ return self
279
+ end
280
+ def replace_node(oldnode, *newnodes)
281
+ oldnode.parent.equal? self or
282
+ raise ArgumentError, "node is not a child"
283
+ index = oldnode.instance_variable_get(:@parent_index)
284
+ self[index, 1] = newnodes
285
+ return self
286
+ end
287
+
288
+ private
289
+
290
+ #
291
+ # Adjust the indices of all elements from index `from_i' to the
292
+ # end.
293
+ #
294
+ def adjust_indices_(from_i)
295
+ (from_i...@array.length).each do |i|
296
+ @array[i].instance_variable_set(:@parent_index, i)
297
+ end
298
+ end
299
+ #
300
+ # Called when something was added.
301
+ #
302
+ def added_(*nodes)
303
+ nodes.each do |n|
304
+ n.instance_variable_set(:@parent, self)
305
+ end
306
+ end
307
+ #
308
+ # Called when something was removed.
309
+ #
310
+ def removed_(*nodes)
311
+ nodes.each do |n|
312
+ n.instance_variable_set(:@parent, nil)
313
+ end
314
+ end
315
+ end
316
+
317
+ class NodeChain
318
+ def node_after(node)
319
+ node.parent.equal? self or
320
+ raise ArgumentError, "node is not a child"
321
+ return node.instance_variable_get(:@next)
322
+ end
323
+ def node_before(node)
324
+ node.parent.equal? self or
325
+ raise ArgumentError, "node is not a child"
326
+ return node.instance_variable_get(:@prev)
327
+ end
328
+ def remove_node(node)
329
+ node.parent.equal? self or
330
+ raise ArgumentError, "node is not a child"
331
+ node_prev = node.instance_variable_get(:@prev)
332
+ node_next = node.instance_variable_get(:@next)
333
+ removed_(node)
334
+ link2_(node_prev, node_next)
335
+ return self
336
+ end
337
+ def insert_after(node, *newnodes)
338
+ node.parent.equal? self or
339
+ raise ArgumentError, "node is not a child"
340
+ newnodes = add_prep(newnodes)
341
+ node_next = node.instance_variable_get(:@next)
342
+ link_(node, newnodes, node_next)
343
+ added_(*newnodes)
344
+ return self
345
+ end
346
+ def insert_before(node, *newnodes)
347
+ node.parent.equal? self or
348
+ raise ArgumentError, "node is not a child"
349
+ newnodes = add_prep(newnodes)
350
+ node_prev = node.instance_variable_get(:@prev)
351
+ link_(node_prev, newnodes, node)
352
+ added_(*newnodes)
353
+ return self
354
+ end
355
+ def replace_node(oldnode, *newnodes)
356
+ oldnode.parent.equal? self or
357
+ raise ArgumentError, "node is not a child"
358
+ newnodes = add_prep(newnodes, [oldnode])
359
+ prev_node = oldnode.instance_variable_get(:@prev)
360
+ next_node = oldnode.instance_variable_get(:@next)
361
+ link_(prev_node, newnodes, next_node)
362
+ removed_(oldnode)
363
+ added_(*newnodes)
364
+ return self
365
+ end
366
+ #
367
+ # Called when something was added.
368
+ #
369
+ def added_(*newnodes)
370
+ newnodes.each{|n| n.instance_variable_set(:@parent, self)}
371
+ @length += newnodes.length
372
+ end
373
+ #
374
+ # Called when something was removed.
375
+ #
376
+ def removed_(*nodes)
377
+ nodes.each{|n| n.instance_variable_set(:@parent, nil)}
378
+ @length -= nodes.length
379
+ end
380
+ end
381
+
382
+ # ------------------------------------------------------------------
383
+ # Array methods
384
+ # ------------------------------------------------------------------
385
+
386
+ class NodeArray
387
+ %w[
388
+ first
389
+ last
390
+ length
391
+ []
392
+ empty?
393
+ index
394
+ rindex
395
+ values_at
396
+ join
397
+ ].each do |m|
398
+ eval "
399
+ def #{m}(*args, &blk)
400
+ @array.#{m}(*args, &blk)
401
+ end
402
+ "
403
+ end
404
+
405
+ %w[
406
+ each
407
+ reverse_each
408
+ each_index
409
+ ].each do |m|
410
+ eval "
411
+ def #{m}(*args, &blk)
412
+ @array.#{m}(*args, &blk)
413
+ return self
414
+ end
415
+ "
416
+ end
417
+
418
+ def to_a
419
+ @array.dup
420
+ end
421
+ def push(*nodes)
422
+ nodes = add_prep(nodes)
423
+ i = @array.length
424
+ @array.push(*nodes)
425
+ added_(*nodes)
426
+ adjust_indices_(i)
427
+ return self
428
+ end
429
+ def unshift(*nodes)
430
+ nodes = add_prep(nodes)
431
+ @array.unshift(*nodes)
432
+ added_(*nodes)
433
+ adjust_indices_(0)
434
+ return self
435
+ end
436
+ def pop(*args)
437
+ if args.empty?
438
+ ret = @array.pop
439
+ removed_(ret)
440
+ return ret
441
+ else
442
+ args.length == 1 or
443
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 0..1)"
444
+ arg = args[0]
445
+ arg = @array.length if @array.length < arg
446
+ ret = @array.slice!(-arg, arg)
447
+ removed_(*ret)
448
+ return ret
449
+ end
450
+ end
451
+ def shift(*args)
452
+ if args.empty?
453
+ ret = @array.shift
454
+ removed_ ret
455
+ else
456
+ args.length == 1 or
457
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 0..1)"
458
+ arg = args[0]
459
+ arg = @array.length if @array.length < arg
460
+ ret = @array.slice!(0, arg)
461
+ removed_(*ret)
462
+ end
463
+ adjust_indices_(0)
464
+ return ret
465
+ end
466
+ def insert(i, *newnodes)
467
+ (0..@array.length).include? i or
468
+ raise IndexError, "index #{i} out of NodeList (length #{@array.length})"
469
+ newnodes = add_prep(newnodes)
470
+ @array.insert(i, *newnodes)
471
+ added_(*newnodes)
472
+ adjust_indices_(i)
473
+ return self
474
+ end
475
+ def <<(newnode)
476
+ newnode, = *add_prep([newnode])
477
+ @array << newnode
478
+ added_(newnode)
479
+ adjust_indices_(@array.length - 1)
480
+ return self
481
+ end
482
+ def []=(*args)
483
+ newnodes = args.pop
484
+ i, n, splat = parse_index(*args)
485
+ oldnodes = @array[i, n] or
486
+ raise IndexError, "index #{i} out of NodeList"
487
+ if splat
488
+ newnodes = add_prep(newnodes, oldnodes)
489
+ else
490
+ # newnodes is a single node (not an Array)
491
+ newnodes = add_prep([newnodes], [oldnodes])
492
+ end
493
+ @array[i, n] = newnodes
494
+ if splat
495
+ removed_(*oldnodes)
496
+ added_(*newnodes)
497
+ else
498
+ removed_(oldnodes)
499
+ added_(newnodes)
500
+ end
501
+ adjust_indices_(i)
502
+ return newnodes
503
+ end
504
+ def concat(other)
505
+ other = other.to_a
506
+ other = add_prep(other)
507
+ len = @array.length
508
+ @array.concat(other)
509
+ added_(*other)
510
+ adjust_indices_(len)
511
+ return self
512
+ end
513
+ def delete_at(index)
514
+ if index < @array.length
515
+ ret = @array.delete_at(index)
516
+ removed_(ret)
517
+ adjust_indices_(index)
518
+ return ret
519
+ else
520
+ return nil
521
+ end
522
+ end
523
+ def clear
524
+ nodes = @array.dup
525
+ @array.clear
526
+ removed_(*nodes)
527
+ return self
528
+ end
529
+ def replace(other)
530
+ other = other.to_a
531
+ other = add_prep(other)
532
+ oldnodes = @array.dup
533
+ @array.replace(other)
534
+ removed_(*oldnodes)
535
+ added_(*@array)
536
+ adjust_indices_(0)
537
+ return self
538
+ end
539
+ end
540
+
541
+ class NodeChain
542
+ #
543
+ # const methods
544
+ #
545
+ def first(n=nil)
546
+ if n.nil?
547
+ return @first
548
+ else
549
+ n = length if n > length
550
+ node = @first
551
+ ret = ::Array.new(n) do
552
+ r = node
553
+ node = node.instance_variable_get(:@next)
554
+ r
555
+ end
556
+ return ret
557
+ end
558
+ end
559
+ def last(n=nil)
560
+ if n.nil?
561
+ return @last
562
+ else
563
+ n = length if n > length
564
+ node = @last
565
+ ret = ::Array.new(n)
566
+ (n-1).downto(0) do |i|
567
+ ret[i] = node
568
+ node = node.instance_variable_get(:@prev)
569
+ end
570
+ return ret
571
+ end
572
+ end
573
+ def length
574
+ @length
575
+ end
576
+ def each
577
+ node = @first
578
+ until node.nil?
579
+ yield node
580
+ node = node.instance_variable_get(:@next)
581
+ end
582
+ return self
583
+ end
584
+ def reverse_each
585
+ node = @last
586
+ until node.nil?
587
+ yield node
588
+ node = node.instance_variable_get(:@prev)
589
+ end
590
+ return self
591
+ end
592
+ def to_a
593
+ node = @first
594
+ ret = ::Array.new(@length) do
595
+ r = node
596
+ node = node.instance_variable_get(:@next)
597
+ r
598
+ end
599
+ return ret
600
+ end
601
+ def [](*args)
602
+ i, n, splat = parse_index(*args)
603
+ return nil if i >= @length
604
+ node = get_(i)
605
+ if splat
606
+ # return an array of Nodes
607
+ n = length-i if n > length-i
608
+ ret = ::Array.new(n) do
609
+ r = node
610
+ node = node.next
611
+ r
612
+ end
613
+ return ret
614
+ else
615
+ # return a Node
616
+ return node
617
+ end
618
+ end
619
+ def each_index
620
+ @length.times{|i| yield i}
621
+ return self
622
+ end
623
+ def empty?
624
+ @length.zero?
625
+ end
626
+ def index(node)
627
+ curr = @first
628
+ i = 0
629
+ while curr
630
+ return i if curr == node
631
+ curr = curr.instance_variable_get(:@next)
632
+ i += 1
633
+ end
634
+ return nil
635
+ end
636
+ def rindex(node)
637
+ curr = @last
638
+ i = @length - 1
639
+ while curr
640
+ return i if curr == node
641
+ curr = curr.instance_variable_get(:@prev)
642
+ i -= 1
643
+ end
644
+ return nil
645
+ end
646
+ def values_at(*args)
647
+ args.map!{|i| self[i]}
648
+ end
649
+ def join(*args)
650
+ self.to_a.join(*args)
651
+ end
652
+
653
+ #
654
+ # non-const methods
655
+ #
656
+ def push(*newnodes)
657
+ newnodes = add_prep(newnodes)
658
+ added_(*newnodes)
659
+ link_(@last, newnodes, nil)
660
+ return self
661
+ end
662
+ def <<(newnode)
663
+ return push(newnode)
664
+ end
665
+ def unshift(*newnodes)
666
+ newnodes = add_prep(newnodes)
667
+ added_(*newnodes)
668
+ link_(nil, newnodes, @first)
669
+ return self
670
+ end
671
+ def pop(n=nil)
672
+ if n
673
+ # return an Array of Nodes
674
+ ret = last(n)
675
+ return ret if ret.empty?
676
+ link2_(ret.first.instance_variable_get(:@prev), nil)
677
+ removed_(*ret)
678
+ return ret
679
+ else
680
+ return nil if empty?
681
+ # return a Node
682
+ ret = @last
683
+ link2_(@last.instance_variable_get(:@prev), nil)
684
+ removed_(ret)
685
+ return ret
686
+ end
687
+ end
688
+ def shift(n=nil)
689
+ if n
690
+ # return an Array of Nodes
691
+ ret = first(n)
692
+ return ret if ret.empty?
693
+ link2_(nil, ret.last.instance_variable_get(:@next))
694
+ removed_(*ret)
695
+ return ret
696
+ else
697
+ return nil if empty?
698
+ # return a Node
699
+ ret = @first
700
+ link2_(nil, @first.instance_variable_get(:@next))
701
+ removed_(ret)
702
+ return ret
703
+ end
704
+ end
705
+ def insert(i, *newnodes)
706
+ (0..@length).include? i or
707
+ raise IndexError, "index #{i} out of NodeList"
708
+ if i == @length
709
+ return push(*newnodes)
710
+ else
711
+ insert_before(self[i], *newnodes)
712
+ end
713
+ end
714
+ def []=(*args)
715
+ newnodes = args.pop
716
+ i, n, splat = parse_index(*args)
717
+ oldnodes = self[i, n] or
718
+ raise IndexError, "index #{i} out of NodeList"
719
+ unless n.zero?
720
+ prev_node = n.instance_variable_get(:@prev)
721
+ next_node = n.instance_variable_get(:@next)
722
+ link2_(prev, next_node)
723
+ removed_(*oldnodes)
724
+ end
725
+ if i == @length
726
+ if splat
727
+ push(*newnodes)
728
+ else
729
+ push(newnodes)
730
+ end
731
+ else
732
+ node = get_(i)
733
+ if splat
734
+ insert_before(node, *newnodes)
735
+ else
736
+ insert_before(node, newnodes)
737
+ end
738
+ end
739
+ return newnodes
740
+ end
741
+ def concat(other)
742
+ return push(*other.to_a)
743
+ end
744
+ def delete_at(index)
745
+ node = self[index]
746
+ remove_node(node)
747
+ return node
748
+ end
749
+ def clear
750
+ each{|n| set_parent(n, nil)}
751
+ @first = @last = nil
752
+ @length = 0
753
+ return self
754
+ end
755
+ def replace(other)
756
+ return clear.push(*other.to_a)
757
+ end
758
+
759
+ private
760
+ #
761
+ # Link up `nodes' between `a' and `b'.
762
+ #
763
+ def link_(a, nodes, b)
764
+ if nodes.empty?
765
+ if a.nil?
766
+ @first = b
767
+ else
768
+ a.instance_variable_set(:@next, b)
769
+ end
770
+ if b.nil?
771
+ @last = a
772
+ else
773
+ b.instance_variable_set(:@prev, a)
774
+ end
775
+ else
776
+ # connect `a' and `b'
777
+ first = nodes.first
778
+ if a.nil?
779
+ @first = first
780
+ else
781
+ a.instance_variable_set(:@next, first)
782
+ end
783
+ last = nodes.last
784
+ if b.nil?
785
+ @last = last
786
+ else
787
+ b.instance_variable_set(:@prev, last)
788
+ end
789
+
790
+ # connect `nodes'
791
+ if nodes.length == 1
792
+ node = nodes[0]
793
+ node.instance_variable_set(:@prev, a)
794
+ node.instance_variable_set(:@next, b)
795
+ else
796
+ first.instance_variable_set(:@next, nodes[ 1])
797
+ first.instance_variable_set(:@prev, a)
798
+ last. instance_variable_set(:@prev, nodes[-2])
799
+ last. instance_variable_set(:@next, b)
800
+ (1...nodes.length-1).each do |i|
801
+ n = nodes[i]
802
+ n.instance_variable_set(:@prev, nodes[i-1])
803
+ n.instance_variable_set(:@next, nodes[i+1])
804
+ end
805
+ end
806
+ end
807
+ end
808
+ #
809
+ # Special case for 2
810
+ #
811
+ def link2_(a, b)
812
+ if a.nil?
813
+ @first = b
814
+ else
815
+ a.instance_variable_set(:@next, b) unless a.nil?
816
+ end
817
+ if b.nil?
818
+ @last = a
819
+ else
820
+ b.instance_variable_set(:@prev, a) unless b.nil?
821
+ end
822
+ end
823
+
824
+ #
825
+ # Return the `i'th Node. Assume `i' is in 0...length.
826
+ #
827
+ def get_(i)
828
+ # return a Node
829
+ if i < (@length >> 1)
830
+ # go from the beginning
831
+ node = @first
832
+ i.times{node = node.next}
833
+ else
834
+ # go from the end
835
+ node = @last
836
+ (@length - 1 - i).times{node = node.prev}
837
+ end
838
+ return node
839
+ end
840
+ end
841
+ end