cast 0.1.0 → 0.2.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.
- data/.gitignore +8 -0
- data/CHANGELOG +50 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.markdown +1948 -0
- data/Rakefile +22 -0
- data/cast.gemspec +20 -0
- data/ext/cast.c +6 -0
- data/ext/extconf.rb +1 -1
- data/ext/parser.c +2 -2
- data/ext/yylex.c +2592 -4171
- data/ext/yylex.re +20 -26
- data/lib/cast.rb +11 -16
- data/lib/cast/c.tab.rb +2252 -2231
- data/lib/cast/c.y +185 -161
- data/lib/cast/c_nodes.rb +181 -391
- data/lib/cast/inspect.rb +8 -10
- data/lib/cast/node.rb +362 -365
- data/lib/cast/node_list.rb +156 -165
- data/lib/cast/parse.rb +86 -65
- data/lib/cast/preprocessor.rb +72 -0
- data/lib/cast/tempfile.rb +33 -0
- data/lib/cast/to_s.rb +83 -75
- data/lib/cast/version.rb +11 -0
- data/test/all.rb +5 -0
- data/test/{test_c_nodes.rb → c_nodes_test.rb} +91 -23
- data/test/lexer_test.rb +323 -0
- data/test/{test_node_list.rb → node_list_test.rb} +367 -396
- data/test/{test_node.rb → node_test.rb} +142 -160
- data/test/{test_parse.rb → parse_test.rb} +63 -17
- data/test/{test_parser.rb → parser_test.rb} +62 -22
- data/test/preprocessor_test.rb +87 -0
- data/test/render_test.rb +2086 -0
- data/test/{run.rb → test_helper.rb} +76 -88
- metadata +100 -54
- data/README +0 -6
- data/doc/index.html +0 -2505
- data/ext/cast_ext.c +0 -10
data/lib/cast/node_list.rb
CHANGED
@@ -1,29 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
### ##################################################################
|
7
|
-
###
|
1
|
+
######################################################################
|
2
|
+
#
|
3
|
+
# NodeList and subclasses.
|
4
|
+
#
|
5
|
+
######################################################################
|
8
6
|
|
9
7
|
module C
|
10
|
-
|
11
|
-
|
8
|
+
# Declare all the classes, so we don't have to declare the
|
9
|
+
# inheritances later.
|
12
10
|
class NodeList < Node; abstract; end
|
13
11
|
class NodeArray < NodeList; end
|
14
12
|
class NodeChain < NodeList; end
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
### NodeList
|
20
|
-
###
|
21
|
-
### Abstract base class of the Node list classes.
|
22
|
-
###
|
23
|
-
### ================================================================
|
24
|
-
###
|
14
|
+
#
|
15
|
+
# Abstract base class of the Node list classes.
|
16
|
+
#
|
25
17
|
class NodeList
|
26
|
-
def self.[]
|
18
|
+
def self.[](*args)
|
27
19
|
new.concat(args)
|
28
20
|
end
|
29
21
|
|
@@ -32,11 +24,11 @@ module C
|
|
32
24
|
length
|
33
25
|
end
|
34
26
|
|
35
|
-
def ==
|
27
|
+
def ==(other)
|
36
28
|
return false if !other.is_a? C::NodeList
|
37
29
|
|
38
|
-
|
39
|
-
|
30
|
+
# none of the NodeList classes here have fields, but there's no
|
31
|
+
# reason why one can't subclass one to have fields
|
40
32
|
fields.each do |field|
|
41
33
|
mine = self .send(field.reader)
|
42
34
|
yours = other.send(field.reader)
|
@@ -69,23 +61,23 @@ module C
|
|
69
61
|
|
70
62
|
protected # -----------------------------------------------------
|
71
63
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
def parse_index
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
89
81
|
case args.length
|
90
82
|
when 1
|
91
83
|
arg = args.first
|
@@ -110,24 +102,24 @@ module C
|
|
110
102
|
end
|
111
103
|
end
|
112
104
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
def wrap_index
|
105
|
+
#
|
106
|
+
# Wrap the given index if less than 0, and return it.
|
107
|
+
#
|
108
|
+
def wrap_index(i)
|
117
109
|
i < 0 ? (i + length) : i
|
118
110
|
end
|
119
111
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
def add_prep
|
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)
|
131
123
|
if oldnodes
|
132
124
|
oldnodes = oldnodes.map{|n| n.object_id}
|
133
125
|
nodes.map! do |node|
|
@@ -147,16 +139,16 @@ module C
|
|
147
139
|
return nodes
|
148
140
|
end
|
149
141
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
def set_parent
|
142
|
+
#
|
143
|
+
# Set the parent of `node' to `val'.
|
144
|
+
#
|
145
|
+
def set_parent(node, val)
|
154
146
|
node.send(:parent=, val)
|
155
147
|
end
|
156
148
|
end
|
157
149
|
|
158
150
|
class NodeArray
|
159
|
-
def assert_invariants
|
151
|
+
def assert_invariants(testcase)
|
160
152
|
super
|
161
153
|
testcase.assert_same(::Array, @array)
|
162
154
|
@array.each_with_index do |node, i|
|
@@ -185,7 +177,7 @@ module C
|
|
185
177
|
end
|
186
178
|
|
187
179
|
class NodeChain
|
188
|
-
def assert_invariants
|
180
|
+
def assert_invariants(testcase)
|
189
181
|
super
|
190
182
|
assert_same(@length.zero?, @first.nil?)
|
191
183
|
assert_same(@length.zero?, @last.nil?)
|
@@ -238,20 +230,18 @@ module C
|
|
238
230
|
end
|
239
231
|
end
|
240
232
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
### ----------------------------------------------------------------
|
245
|
-
###
|
233
|
+
# ------------------------------------------------------------------
|
234
|
+
# Methods called from children
|
235
|
+
# ------------------------------------------------------------------
|
246
236
|
|
247
237
|
class NodeArray
|
248
|
-
def node_after
|
238
|
+
def node_after(node)
|
249
239
|
node.parent.equal? self or
|
250
240
|
raise ArgumentError, "node is not a child"
|
251
241
|
@array[index = node.instance_variable_get(:@parent_index)+1]
|
252
242
|
end
|
253
243
|
|
254
|
-
def node_before
|
244
|
+
def node_before(node)
|
255
245
|
node.parent.equal? self or
|
256
246
|
raise ArgumentError, "node is not a child"
|
257
247
|
index = node.instance_variable_get(:@parent_index)
|
@@ -262,7 +252,7 @@ module C
|
|
262
252
|
end
|
263
253
|
end
|
264
254
|
|
265
|
-
def remove_node
|
255
|
+
def remove_node(node)
|
266
256
|
node.parent.equal? self or
|
267
257
|
raise ArgumentError, "node is not a child"
|
268
258
|
index = node.instance_variable_get(:@parent_index)
|
@@ -273,21 +263,21 @@ module C
|
|
273
263
|
return self
|
274
264
|
end
|
275
265
|
|
276
|
-
def insert_after
|
266
|
+
def insert_after(node, *newnodes)
|
277
267
|
node.parent.equal? self or
|
278
268
|
raise ArgumentError, "node is not a child"
|
279
269
|
index = node.instance_variable_get(:@parent_index) + 1
|
280
270
|
insert(index, *newnodes)
|
281
271
|
return self
|
282
272
|
end
|
283
|
-
def insert_before
|
273
|
+
def insert_before(node, *newnodes)
|
284
274
|
node.parent.equal? self or
|
285
275
|
raise ArgumentError, "node is not a child"
|
286
276
|
index = node.instance_variable_get(:@parent_index)
|
287
277
|
insert(index, *newnodes)
|
288
278
|
return self
|
289
279
|
end
|
290
|
-
def replace_node
|
280
|
+
def replace_node(oldnode, *newnodes)
|
291
281
|
oldnode.parent.equal? self or
|
292
282
|
raise ArgumentError, "node is not a child"
|
293
283
|
index = oldnode.instance_variable_get(:@parent_index)
|
@@ -297,27 +287,27 @@ module C
|
|
297
287
|
|
298
288
|
private
|
299
289
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
def adjust_indices_
|
290
|
+
#
|
291
|
+
# Adjust the indices of all elements from index `from_i' to the
|
292
|
+
# end.
|
293
|
+
#
|
294
|
+
def adjust_indices_(from_i)
|
305
295
|
(from_i...@array.length).each do |i|
|
306
296
|
@array[i].instance_variable_set(:@parent_index, i)
|
307
297
|
end
|
308
298
|
end
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
def added_
|
299
|
+
#
|
300
|
+
# Called when something was added.
|
301
|
+
#
|
302
|
+
def added_(*nodes)
|
313
303
|
nodes.each do |n|
|
314
304
|
n.instance_variable_set(:@parent, self)
|
315
305
|
end
|
316
306
|
end
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
def removed_
|
307
|
+
#
|
308
|
+
# Called when something was removed.
|
309
|
+
#
|
310
|
+
def removed_(*nodes)
|
321
311
|
nodes.each do |n|
|
322
312
|
n.instance_variable_set(:@parent, nil)
|
323
313
|
end
|
@@ -325,17 +315,17 @@ module C
|
|
325
315
|
end
|
326
316
|
|
327
317
|
class NodeChain
|
328
|
-
def node_after
|
318
|
+
def node_after(node)
|
329
319
|
node.parent.equal? self or
|
330
320
|
raise ArgumentError, "node is not a child"
|
331
321
|
return node.instance_variable_get(:@next)
|
332
322
|
end
|
333
|
-
def node_before
|
323
|
+
def node_before(node)
|
334
324
|
node.parent.equal? self or
|
335
325
|
raise ArgumentError, "node is not a child"
|
336
326
|
return node.instance_variable_get(:@prev)
|
337
327
|
end
|
338
|
-
def remove_node
|
328
|
+
def remove_node(node)
|
339
329
|
node.parent.equal? self or
|
340
330
|
raise ArgumentError, "node is not a child"
|
341
331
|
node_prev = node.instance_variable_get(:@prev)
|
@@ -344,7 +334,7 @@ module C
|
|
344
334
|
link2_(node_prev, node_next)
|
345
335
|
return self
|
346
336
|
end
|
347
|
-
def insert_after
|
337
|
+
def insert_after(node, *newnodes)
|
348
338
|
node.parent.equal? self or
|
349
339
|
raise ArgumentError, "node is not a child"
|
350
340
|
newnodes = add_prep(newnodes)
|
@@ -353,7 +343,7 @@ module C
|
|
353
343
|
added_(*newnodes)
|
354
344
|
return self
|
355
345
|
end
|
356
|
-
def insert_before
|
346
|
+
def insert_before(node, *newnodes)
|
357
347
|
node.parent.equal? self or
|
358
348
|
raise ArgumentError, "node is not a child"
|
359
349
|
newnodes = add_prep(newnodes)
|
@@ -362,7 +352,7 @@ module C
|
|
362
352
|
added_(*newnodes)
|
363
353
|
return self
|
364
354
|
end
|
365
|
-
def replace_node
|
355
|
+
def replace_node(oldnode, *newnodes)
|
366
356
|
oldnode.parent.equal? self or
|
367
357
|
raise ArgumentError, "node is not a child"
|
368
358
|
newnodes = add_prep(newnodes, [oldnode])
|
@@ -373,27 +363,25 @@ module C
|
|
373
363
|
added_(*newnodes)
|
374
364
|
return self
|
375
365
|
end
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
def added_
|
366
|
+
#
|
367
|
+
# Called when something was added.
|
368
|
+
#
|
369
|
+
def added_(*newnodes)
|
380
370
|
newnodes.each{|n| n.instance_variable_set(:@parent, self)}
|
381
371
|
@length += newnodes.length
|
382
372
|
end
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
def removed_
|
373
|
+
#
|
374
|
+
# Called when something was removed.
|
375
|
+
#
|
376
|
+
def removed_(*nodes)
|
387
377
|
nodes.each{|n| n.instance_variable_set(:@parent, nil)}
|
388
378
|
@length -= nodes.length
|
389
379
|
end
|
390
380
|
end
|
391
381
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
### ----------------------------------------------------------------
|
396
|
-
###
|
382
|
+
# ------------------------------------------------------------------
|
383
|
+
# Array methods
|
384
|
+
# ------------------------------------------------------------------
|
397
385
|
|
398
386
|
class NodeArray
|
399
387
|
%w[
|
@@ -408,8 +396,8 @@ module C
|
|
408
396
|
join
|
409
397
|
].each do |m|
|
410
398
|
eval "
|
411
|
-
def #{m}
|
412
|
-
@array.#{m}
|
399
|
+
def #{m}(*args, &blk)
|
400
|
+
@array.#{m}(*args, &blk)
|
413
401
|
end
|
414
402
|
"
|
415
403
|
end
|
@@ -420,8 +408,8 @@ module C
|
|
420
408
|
each_index
|
421
409
|
].each do |m|
|
422
410
|
eval "
|
423
|
-
def #{m}
|
424
|
-
@array.#{m}
|
411
|
+
def #{m}(*args, &blk)
|
412
|
+
@array.#{m}(*args, &blk)
|
425
413
|
return self
|
426
414
|
end
|
427
415
|
"
|
@@ -430,7 +418,7 @@ module C
|
|
430
418
|
def to_a
|
431
419
|
@array.dup
|
432
420
|
end
|
433
|
-
def push
|
421
|
+
def push(*nodes)
|
434
422
|
nodes = add_prep(nodes)
|
435
423
|
i = @array.length
|
436
424
|
@array.push(*nodes)
|
@@ -438,14 +426,14 @@ module C
|
|
438
426
|
adjust_indices_(i)
|
439
427
|
return self
|
440
428
|
end
|
441
|
-
def unshift
|
429
|
+
def unshift(*nodes)
|
442
430
|
nodes = add_prep(nodes)
|
443
431
|
@array.unshift(*nodes)
|
444
432
|
added_(*nodes)
|
445
433
|
adjust_indices_(0)
|
446
434
|
return self
|
447
435
|
end
|
448
|
-
def pop
|
436
|
+
def pop(*args)
|
449
437
|
if args.empty?
|
450
438
|
ret = @array.pop
|
451
439
|
removed_(ret)
|
@@ -456,11 +444,11 @@ module C
|
|
456
444
|
arg = args[0]
|
457
445
|
arg = @array.length if @array.length < arg
|
458
446
|
ret = @array.slice!(-arg, arg)
|
459
|
-
removed_
|
447
|
+
removed_(*ret)
|
460
448
|
return ret
|
461
449
|
end
|
462
450
|
end
|
463
|
-
def shift
|
451
|
+
def shift(*args)
|
464
452
|
if args.empty?
|
465
453
|
ret = @array.shift
|
466
454
|
removed_ ret
|
@@ -470,12 +458,12 @@ module C
|
|
470
458
|
arg = args[0]
|
471
459
|
arg = @array.length if @array.length < arg
|
472
460
|
ret = @array.slice!(0, arg)
|
473
|
-
removed_
|
461
|
+
removed_(*ret)
|
474
462
|
end
|
475
463
|
adjust_indices_(0)
|
476
464
|
return ret
|
477
465
|
end
|
478
|
-
def insert
|
466
|
+
def insert(i, *newnodes)
|
479
467
|
(0..@array.length).include? i or
|
480
468
|
raise IndexError, "index #{i} out of NodeList (length #{@array.length})"
|
481
469
|
newnodes = add_prep(newnodes)
|
@@ -484,14 +472,14 @@ module C
|
|
484
472
|
adjust_indices_(i)
|
485
473
|
return self
|
486
474
|
end
|
487
|
-
def <<
|
488
|
-
newnode = *add_prep([newnode])
|
475
|
+
def <<(newnode)
|
476
|
+
newnode, = *add_prep([newnode])
|
489
477
|
@array << newnode
|
490
478
|
added_(newnode)
|
491
479
|
adjust_indices_(@array.length - 1)
|
492
480
|
return self
|
493
481
|
end
|
494
|
-
def []=
|
482
|
+
def []=(*args)
|
495
483
|
newnodes = args.pop
|
496
484
|
i, n, splat = parse_index(*args)
|
497
485
|
oldnodes = @array[i, n] or
|
@@ -499,7 +487,7 @@ module C
|
|
499
487
|
if splat
|
500
488
|
newnodes = add_prep(newnodes, oldnodes)
|
501
489
|
else
|
502
|
-
|
490
|
+
# newnodes is a single node (not an Array)
|
503
491
|
newnodes = add_prep([newnodes], [oldnodes])
|
504
492
|
end
|
505
493
|
@array[i, n] = newnodes
|
@@ -513,7 +501,7 @@ module C
|
|
513
501
|
adjust_indices_(i)
|
514
502
|
return newnodes
|
515
503
|
end
|
516
|
-
def concat
|
504
|
+
def concat(other)
|
517
505
|
other = other.to_a
|
518
506
|
other = add_prep(other)
|
519
507
|
len = @array.length
|
@@ -522,7 +510,7 @@ module C
|
|
522
510
|
adjust_indices_(len)
|
523
511
|
return self
|
524
512
|
end
|
525
|
-
def delete_at
|
513
|
+
def delete_at(index)
|
526
514
|
if index < @array.length
|
527
515
|
ret = @array.delete_at(index)
|
528
516
|
removed_(ret)
|
@@ -538,7 +526,7 @@ module C
|
|
538
526
|
removed_(*nodes)
|
539
527
|
return self
|
540
528
|
end
|
541
|
-
def replace
|
529
|
+
def replace(other)
|
542
530
|
other = other.to_a
|
543
531
|
other = add_prep(other)
|
544
532
|
oldnodes = @array.dup
|
@@ -551,10 +539,10 @@ module C
|
|
551
539
|
end
|
552
540
|
|
553
541
|
class NodeChain
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
def first
|
542
|
+
#
|
543
|
+
# const methods
|
544
|
+
#
|
545
|
+
def first(n=nil)
|
558
546
|
if n.nil?
|
559
547
|
return @first
|
560
548
|
else
|
@@ -568,7 +556,7 @@ module C
|
|
568
556
|
return ret
|
569
557
|
end
|
570
558
|
end
|
571
|
-
def last
|
559
|
+
def last(n=nil)
|
572
560
|
if n.nil?
|
573
561
|
return @last
|
574
562
|
else
|
@@ -610,12 +598,12 @@ module C
|
|
610
598
|
end
|
611
599
|
return ret
|
612
600
|
end
|
613
|
-
def []
|
601
|
+
def [](*args)
|
614
602
|
i, n, splat = parse_index(*args)
|
615
603
|
return nil if i >= @length
|
616
604
|
node = get_(i)
|
617
605
|
if splat
|
618
|
-
|
606
|
+
# return an array of Nodes
|
619
607
|
n = length-i if n > length-i
|
620
608
|
ret = ::Array.new(n) do
|
621
609
|
r = node
|
@@ -624,7 +612,7 @@ module C
|
|
624
612
|
end
|
625
613
|
return ret
|
626
614
|
else
|
627
|
-
|
615
|
+
# return a Node
|
628
616
|
return node
|
629
617
|
end
|
630
618
|
end
|
@@ -635,7 +623,7 @@ module C
|
|
635
623
|
def empty?
|
636
624
|
@length.zero?
|
637
625
|
end
|
638
|
-
def index
|
626
|
+
def index(node)
|
639
627
|
curr = @first
|
640
628
|
i = 0
|
641
629
|
while curr
|
@@ -645,7 +633,7 @@ module C
|
|
645
633
|
end
|
646
634
|
return nil
|
647
635
|
end
|
648
|
-
def rindex
|
636
|
+
def rindex(node)
|
649
637
|
curr = @last
|
650
638
|
i = @length - 1
|
651
639
|
while curr
|
@@ -655,34 +643,34 @@ module C
|
|
655
643
|
end
|
656
644
|
return nil
|
657
645
|
end
|
658
|
-
def values_at
|
646
|
+
def values_at(*args)
|
659
647
|
args.map!{|i| self[i]}
|
660
648
|
end
|
661
|
-
def join
|
649
|
+
def join(*args)
|
662
650
|
self.to_a.join(*args)
|
663
651
|
end
|
664
652
|
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
def push
|
653
|
+
#
|
654
|
+
# non-const methods
|
655
|
+
#
|
656
|
+
def push(*newnodes)
|
669
657
|
newnodes = add_prep(newnodes)
|
670
658
|
added_(*newnodes)
|
671
659
|
link_(@last, newnodes, nil)
|
672
660
|
return self
|
673
661
|
end
|
674
|
-
def <<
|
662
|
+
def <<(newnode)
|
675
663
|
return push(newnode)
|
676
664
|
end
|
677
|
-
def unshift
|
665
|
+
def unshift(*newnodes)
|
678
666
|
newnodes = add_prep(newnodes)
|
679
667
|
added_(*newnodes)
|
680
668
|
link_(nil, newnodes, @first)
|
681
669
|
return self
|
682
670
|
end
|
683
|
-
def pop
|
671
|
+
def pop(n=nil)
|
684
672
|
if n
|
685
|
-
|
673
|
+
# return an Array of Nodes
|
686
674
|
ret = last(n)
|
687
675
|
return ret if ret.empty?
|
688
676
|
link2_(ret.first.instance_variable_get(:@prev), nil)
|
@@ -690,16 +678,16 @@ module C
|
|
690
678
|
return ret
|
691
679
|
else
|
692
680
|
return nil if empty?
|
693
|
-
|
681
|
+
# return a Node
|
694
682
|
ret = @last
|
695
683
|
link2_(@last.instance_variable_get(:@prev), nil)
|
696
684
|
removed_(ret)
|
697
685
|
return ret
|
698
686
|
end
|
699
687
|
end
|
700
|
-
def shift
|
688
|
+
def shift(n=nil)
|
701
689
|
if n
|
702
|
-
|
690
|
+
# return an Array of Nodes
|
703
691
|
ret = first(n)
|
704
692
|
return ret if ret.empty?
|
705
693
|
link2_(nil, ret.last.instance_variable_get(:@next))
|
@@ -707,14 +695,14 @@ module C
|
|
707
695
|
return ret
|
708
696
|
else
|
709
697
|
return nil if empty?
|
710
|
-
|
698
|
+
# return a Node
|
711
699
|
ret = @first
|
712
700
|
link2_(nil, @first.instance_variable_get(:@next))
|
713
701
|
removed_(ret)
|
714
702
|
return ret
|
715
703
|
end
|
716
704
|
end
|
717
|
-
def insert
|
705
|
+
def insert(i, *newnodes)
|
718
706
|
(0..@length).include? i or
|
719
707
|
raise IndexError, "index #{i} out of NodeList"
|
720
708
|
if i == @length
|
@@ -723,7 +711,7 @@ module C
|
|
723
711
|
insert_before(self[i], *newnodes)
|
724
712
|
end
|
725
713
|
end
|
726
|
-
def []=
|
714
|
+
def []=(*args)
|
727
715
|
newnodes = args.pop
|
728
716
|
i, n, splat = parse_index(*args)
|
729
717
|
oldnodes = self[i, n] or
|
@@ -750,10 +738,10 @@ module C
|
|
750
738
|
end
|
751
739
|
return newnodes
|
752
740
|
end
|
753
|
-
def concat
|
741
|
+
def concat(other)
|
754
742
|
return push(*other.to_a)
|
755
743
|
end
|
756
|
-
def delete_at
|
744
|
+
def delete_at(index)
|
757
745
|
node = self[index]
|
758
746
|
remove_node(node)
|
759
747
|
return node
|
@@ -764,15 +752,15 @@ module C
|
|
764
752
|
@length = 0
|
765
753
|
return self
|
766
754
|
end
|
767
|
-
def replace
|
755
|
+
def replace(other)
|
768
756
|
return clear.push(*other.to_a)
|
769
757
|
end
|
770
758
|
|
771
759
|
private
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
def link_
|
760
|
+
#
|
761
|
+
# Link up `nodes' between `a' and `b'.
|
762
|
+
#
|
763
|
+
def link_(a, nodes, b)
|
776
764
|
if nodes.empty?
|
777
765
|
if a.nil?
|
778
766
|
@first = b
|
@@ -785,7 +773,7 @@ module C
|
|
785
773
|
b.instance_variable_set(:@prev, a)
|
786
774
|
end
|
787
775
|
else
|
788
|
-
|
776
|
+
# connect `a' and `b'
|
789
777
|
first = nodes.first
|
790
778
|
if a.nil?
|
791
779
|
@first = first
|
@@ -799,7 +787,7 @@ module C
|
|
799
787
|
b.instance_variable_set(:@prev, last)
|
800
788
|
end
|
801
789
|
|
802
|
-
|
790
|
+
# connect `nodes'
|
803
791
|
if nodes.length == 1
|
804
792
|
node = nodes[0]
|
805
793
|
node.instance_variable_set(:@prev, a)
|
@@ -817,8 +805,10 @@ module C
|
|
817
805
|
end
|
818
806
|
end
|
819
807
|
end
|
820
|
-
|
821
|
-
|
808
|
+
#
|
809
|
+
# Special case for 2
|
810
|
+
#
|
811
|
+
def link2_(a, b)
|
822
812
|
if a.nil?
|
823
813
|
@first = b
|
824
814
|
else
|
@@ -830,17 +820,18 @@ module C
|
|
830
820
|
b.instance_variable_set(:@prev, a) unless b.nil?
|
831
821
|
end
|
832
822
|
end
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
823
|
+
|
824
|
+
#
|
825
|
+
# Return the `i'th Node. Assume `i' is in 0...length.
|
826
|
+
#
|
827
|
+
def get_(i)
|
828
|
+
# return a Node
|
838
829
|
if i < (@length >> 1)
|
839
|
-
|
830
|
+
# go from the beginning
|
840
831
|
node = @first
|
841
832
|
i.times{node = node.next}
|
842
833
|
else
|
843
|
-
|
834
|
+
# go from the end
|
844
835
|
node = @last
|
845
836
|
(@length - 1 - i).times{node = node.prev}
|
846
837
|
end
|