cast19 0.1.0

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