csquare-cast 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.map(&:inspect).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.first
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