cast19 0.1.0

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