Class: C::NodeChain

Inherits:
NodeList show all
Defined in:
lib/cast/node_list.rb,
lib/cast/node_list.rb,
lib/cast/node_list.rb,
lib/cast/node_list.rb

Constant Summary

Constants inherited from Node

C::Node::INSPECT_TAB

Instance Attribute Summary

Attributes inherited from Node

#parent, #pos, #subclasses

Instance Method Summary collapse

Methods inherited from NodeList

#==, [], #hash, #inspect, #match?, #size, #to_s

Methods inherited from Node

#==, #=~, abstract, add_field, #attached?, child, #depth_first, #detach, #detached?, #eql?, field, fields, #fields, #hash, inherited, initializer, #insert_next, #insert_prev, #inspect, inspect1, #list_next, #list_prev, #match?, #method_missing, new_at, #next, #postorder, #preorder, #prev, #replace_with, #reverse_depth_first, #reverse_postorder, #reverse_preorder, subclasses_recursive, #swap_with

Constructor Details

#initializeNodeChain

Returns a new instance of NodeChain.



205
206
207
208
209
210
# File 'lib/cast/node_list.rb', line 205

def initialize
  super
  @first = nil
  @last  = nil
  @length = 0
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class C::Node

Instance Method Details

#<<(newnode) ⇒ Object



662
663
664
# File 'lib/cast/node_list.rb', line 662

def <<(newnode)
  return push(newnode)
end

#[](*args) ⇒ Object



601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
# File 'lib/cast/node_list.rb', line 601

def [](*args)
  i, n, splat = parse_index(*args)
  return nil if i >= @length
  node = get_(i)
  if splat
    # return an array of Nodes
    n = length-i if n > length-i
    ret = ::Array.new(n) do
      r = node
      node = node.next
      r
    end
    return ret
  else
    # return a Node
    return node
  end
end

#[]=(*args) ⇒ Object



714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
# File 'lib/cast/node_list.rb', line 714

def []=(*args)
  newnodes = args.pop
  i, n, splat = parse_index(*args)
  oldnodes = self[i, n] or
    raise IndexError, "index #{i} out of NodeList"
  unless n.zero?
    prev_node = n.instance_variable_get(:@prev)
    next_node = n.instance_variable_get(:@next)
    link2_(prev, next_node)
    removed_(*oldnodes)
  end
  if i == @length
    if splat
      push(*newnodes)
    else
      push(newnodes)
    end
  else
    node = get_(i)
    if splat
      insert_before(node, *newnodes)
    else
      insert_before(node, newnodes)
    end
  end
  return newnodes
end

#added_(*newnodes) ⇒ Object

Called when something was added.



369
370
371
372
# File 'lib/cast/node_list.rb', line 369

def added_(*newnodes)
  newnodes.each{|n| n.instance_variable_set(:@parent, self)}
  @length += newnodes.length
end

#assert_invariants(testcase) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/cast/node_list.rb', line 180

def assert_invariants(testcase)
  super
  assert_same(@length.zero?, @first.nil?)
  assert_same(@length.zero?, @last.nil?)
  unless @length.zero?
    assert_same(@first, self[0])
    assert_same(@last, self[@length-1])
    (0...@length.times).each do |i|
      nodeprev = self[i].instance_variable_get(:@prev)
      nodenext = self[i].instance_variable_get(:@next)
      if i == 0
        assert_nil(nodeprev)
      else
        assert_same(self[i-1], nodeprev)
      end

      if i == @length-1
        assert_nil(nodenext)
      else
        assert_same(self[i+1], nodenext)
      end
    end
  end
end

#clearObject



749
750
751
752
753
754
# File 'lib/cast/node_list.rb', line 749

def clear
  each{|n| set_parent(n, nil)}
  @first = @last = nil
  @length = 0
  return self
end

#cloneObject



222
223
224
225
226
227
228
229
230
# File 'lib/cast/node_list.rb', line 222

def clone
  ret = super
  ret.instance_variable_set(:@first, nil)
  ret.instance_variable_set(:@last, nil)
  ret.instance_variable_set(:@length, 0)
  clones = self.map{|n| n.clone}
  ret.push(*clones)
  return ret
end

#concat(other) ⇒ Object



741
742
743
# File 'lib/cast/node_list.rb', line 741

def concat(other)
  return push(*other.to_a)
end

#delete_at(index) ⇒ Object



744
745
746
747
748
# File 'lib/cast/node_list.rb', line 744

def delete_at(index)
  node = self[index]
  remove_node(node)
  return node
end

#dupObject



212
213
214
215
216
217
218
219
220
# File 'lib/cast/node_list.rb', line 212

def dup
  ret = super
  ret.instance_variable_set(:@first, nil)
  ret.instance_variable_set(:@last, nil)
  ret.instance_variable_set(:@length, 0)
  dupes = self.map{|n| n.dup}
  ret.push(*dupes)
  return ret
end

#eachObject



576
577
578
579
580
581
582
583
# File 'lib/cast/node_list.rb', line 576

def each
  node = @first
  until node.nil?
    yield node
    node = node.instance_variable_get(:@next)
  end
  return self
end

#each_indexObject



619
620
621
622
# File 'lib/cast/node_list.rb', line 619

def each_index
  @length.times{|i| yield i}
  return self
end

#empty?Boolean

Returns:

  • (Boolean)


623
624
625
# File 'lib/cast/node_list.rb', line 623

def empty?
  @length.zero?
end

#first(n = nil) ⇒ Object

const methods



545
546
547
548
549
550
551
552
553
554
555
556
557
558
# File 'lib/cast/node_list.rb', line 545

def first(n=nil)
  if n.nil?
    return @first
  else
    n = length if n > length
    node = @first
    ret = ::Array.new(n) do
      r = node
      node = node.instance_variable_get(:@next)
      r
    end
    return ret
  end
end

#index(node) ⇒ Object



626
627
628
629
630
631
632
633
634
635
# File 'lib/cast/node_list.rb', line 626

def index(node)
  curr = @first
  i = 0
  while curr
    return i if curr == node
    curr = curr.instance_variable_get(:@next)
    i += 1
  end
  return nil
end

#insert(i, *newnodes) ⇒ Object



705
706
707
708
709
710
711
712
713
# File 'lib/cast/node_list.rb', line 705

def insert(i, *newnodes)
  (0..@length).include? i or
    raise IndexError, "index #{i} out of NodeList"
  if i == @length
    return push(*newnodes)
  else
    insert_before(self[i], *newnodes)
  end
end

#insert_after(node, *newnodes) ⇒ Object



337
338
339
340
341
342
343
344
345
# File 'lib/cast/node_list.rb', line 337

def insert_after(node, *newnodes)
  node.parent.equal? self or
    raise ArgumentError, "node is not a child"
  newnodes = add_prep(newnodes)
  node_next = node.instance_variable_get(:@next)
  link_(node, newnodes, node_next)
  added_(*newnodes)
  return self
end

#insert_before(node, *newnodes) ⇒ Object



346
347
348
349
350
351
352
353
354
# File 'lib/cast/node_list.rb', line 346

def insert_before(node, *newnodes)
  node.parent.equal? self or
    raise ArgumentError, "node is not a child"
  newnodes = add_prep(newnodes)
  node_prev = node.instance_variable_get(:@prev)
  link_(node_prev, newnodes, node)
  added_(*newnodes)
  return self
end

#join(*args) ⇒ Object



649
650
651
# File 'lib/cast/node_list.rb', line 649

def join(*args)
  self.to_a.join(*args)
end

#last(n = nil) ⇒ Object



559
560
561
562
563
564
565
566
567
568
569
570
571
572
# File 'lib/cast/node_list.rb', line 559

def last(n=nil)
  if n.nil?
    return @last
  else
    n = length if n > length
    node = @last
    ret = ::Array.new(n)
    (n-1).downto(0) do |i|
      ret[i] = node
      node = node.instance_variable_get(:@prev)
    end
    return ret
  end
end

#lengthObject



573
574
575
# File 'lib/cast/node_list.rb', line 573

def length
  @length
end

#node_after(node) ⇒ Object



318
319
320
321
322
# File 'lib/cast/node_list.rb', line 318

def node_after(node)
  node.parent.equal? self or
    raise ArgumentError, "node is not a child"
  return node.instance_variable_get(:@next)
end

#node_before(node) ⇒ Object



323
324
325
326
327
# File 'lib/cast/node_list.rb', line 323

def node_before(node)
  node.parent.equal? self or
    raise ArgumentError, "node is not a child"
  return node.instance_variable_get(:@prev)
end

#pop(n = nil) ⇒ Object



671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
# File 'lib/cast/node_list.rb', line 671

def pop(n=nil)
  if n
    # return an Array of Nodes
    ret = last(n)
    return ret if ret.empty?
    link2_(ret.first.instance_variable_get(:@prev), nil)
    removed_(*ret)
    return ret
  else
    return nil if empty?
    # return a Node
    ret = @last
    link2_(@last.instance_variable_get(:@prev), nil)
    removed_(ret)
    return ret
  end
end

#push(*newnodes) ⇒ Object

non-const methods



656
657
658
659
660
661
# File 'lib/cast/node_list.rb', line 656

def push(*newnodes)
  newnodes = add_prep(newnodes)
  added_(*newnodes)
  link_(@last, newnodes, nil)
  return self
end

#remove_node(node) ⇒ Object



328
329
330
331
332
333
334
335
336
# File 'lib/cast/node_list.rb', line 328

def remove_node(node)
  node.parent.equal? self or
    raise ArgumentError, "node is not a child"
  node_prev = node.instance_variable_get(:@prev)
  node_next = node.instance_variable_get(:@next)
  removed_(node)
  link2_(node_prev, node_next)
  return self
end

#removed_(*nodes) ⇒ Object

Called when something was removed.



376
377
378
379
# File 'lib/cast/node_list.rb', line 376

def removed_(*nodes)
  nodes.each{|n| n.instance_variable_set(:@parent, nil)}
  @length -= nodes.length
end

#replace(other) ⇒ Object



755
756
757
# File 'lib/cast/node_list.rb', line 755

def replace(other)
  return clear.push(*other.to_a)
end

#replace_node(oldnode, *newnodes) ⇒ Object



355
356
357
358
359
360
361
362
363
364
365
# File 'lib/cast/node_list.rb', line 355

def replace_node(oldnode, *newnodes)
  oldnode.parent.equal? self or
    raise ArgumentError, "node is not a child"
  newnodes = add_prep(newnodes, [oldnode])
  prev_node = oldnode.instance_variable_get(:@prev)
  next_node = oldnode.instance_variable_get(:@next)
  link_(prev_node, newnodes, next_node)
  removed_(oldnode)
  added_(*newnodes)
  return self
end

#reverse_eachObject



584
585
586
587
588
589
590
591
# File 'lib/cast/node_list.rb', line 584

def reverse_each
  node = @last
  until node.nil?
    yield node
    node = node.instance_variable_get(:@prev)
  end
  return self
end

#rindex(node) ⇒ Object



636
637
638
639
640
641
642
643
644
645
# File 'lib/cast/node_list.rb', line 636

def rindex(node)
  curr = @last
  i = @length - 1
  while curr
    return i if curr == node
    curr = curr.instance_variable_get(:@prev)
    i -= 1
  end
  return nil
end

#shift(n = nil) ⇒ Object



688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
# File 'lib/cast/node_list.rb', line 688

def shift(n=nil)
  if n
    # return an Array of Nodes
    ret = first(n)
    return ret if ret.empty?
    link2_(nil, ret.last.instance_variable_get(:@next))
    removed_(*ret)
    return ret
  else
    return nil if empty?
    # return a Node
    ret = @first
    link2_(nil, @first.instance_variable_get(:@next))
    removed_(ret)
    return ret
  end
end

#to_aObject



592
593
594
595
596
597
598
599
600
# File 'lib/cast/node_list.rb', line 592

def to_a
  node = @first
  ret = ::Array.new(@length) do
    r = node
    node = node.instance_variable_get(:@next)
    r
  end
  return ret
end

#unshift(*newnodes) ⇒ Object



665
666
667
668
669
670
# File 'lib/cast/node_list.rb', line 665

def unshift(*newnodes)
  newnodes = add_prep(newnodes)
  added_(*newnodes)
  link_(nil, newnodes, @first)
  return self
end

#values_at(*args) ⇒ Object



646
647
648
# File 'lib/cast/node_list.rb', line 646

def values_at(*args)
  args.map!{|i| self[i]}
end