cast 0.0.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/CHANGELOG +63 -0
- data/Gemfile +9 -0
- data/LICENSE +22 -0
- data/README.markdown +1924 -0
- data/Rakefile +29 -0
- data/cast.gemspec +18 -0
- data/ext/cast.c +6 -0
- data/ext/cast.h +141 -0
- data/ext/extconf.rb +2 -0
- data/ext/parser.c +287 -0
- data/ext/yylex.re +340 -0
- data/lib/cast.rb +11 -9
- data/lib/cast/c.y +904 -0
- data/lib/{c_nodes.rb → cast/c_nodes.rb} +188 -392
- data/lib/{to_debug.rb → cast/inspect.rb} +18 -20
- data/lib/cast/node.rb +741 -0
- data/lib/{node_list.rb → cast/node_list.rb} +175 -176
- data/lib/{parse.rb → cast/parse.rb} +86 -65
- data/lib/cast/preprocessor.rb +59 -0
- data/lib/cast/tempfile.rb +33 -0
- data/lib/{to_s.rb → cast/to_s.rb} +133 -80
- data/lib/cast/version.rb +11 -0
- data/test/c_nodes_test.rb +224 -0
- data/test/lexer_test.rb +335 -0
- data/test/{test_node_list.rb → node_list_test.rb} +401 -413
- data/test/{test_node.rb → node_test.rb} +186 -214
- data/test/parse_test.rb +2068 -0
- data/test/{test_parser.rb → parser_test.rb} +145 -58
- data/test/preprocessor_test.rb +85 -0
- data/test/render_test.rb +2116 -0
- data/test/test_helper.rb +198 -0
- metadata +83 -52
- data/README +0 -6
- data/doc/index.html +0 -2513
- data/install.rb +0 -14
- data/lib/c.tab.rb +0 -3433
- data/lib/c.y +0 -935
- data/lib/node.rb +0 -744
- data/test/common.rb +0 -174
- data/test/run.rb +0 -5
- data/test/test_c_nodes.rb +0 -160
- data/test/test_parse.rb +0 -2014
@@ -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,56 +230,54 @@ 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
|
-
@array[
|
241
|
+
@array[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)
|
258
248
|
if index.zero?
|
259
249
|
return nil
|
260
250
|
else
|
261
|
-
return @array[index-1]
|
251
|
+
return @array[index - 1]
|
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)
|
269
|
-
|
259
|
+
node.instance_variable_set(:@parent_index, nil)
|
270
260
|
removed_(@array[index])
|
271
261
|
@array.delete_at(index)
|
272
262
|
adjust_indices_(index)
|
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,36 +426,44 @@ 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
|
-
ret = @array.pop
|
451
|
-
|
438
|
+
ret = @array.pop and
|
439
|
+
removed_(ret)
|
452
440
|
return ret
|
453
441
|
else
|
454
|
-
|
455
|
-
|
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)
|
456
448
|
return ret
|
457
449
|
end
|
458
450
|
end
|
459
|
-
def shift
|
451
|
+
def shift(*args)
|
460
452
|
if args.empty?
|
461
|
-
ret = @array.shift
|
462
|
-
|
453
|
+
ret = @array.shift and
|
454
|
+
removed_ ret
|
463
455
|
else
|
464
|
-
|
465
|
-
|
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)
|
466
462
|
end
|
467
|
-
adjust_indices_(0)
|
463
|
+
adjust_indices_(0) unless ret.nil?
|
468
464
|
return ret
|
469
465
|
end
|
470
|
-
def insert
|
466
|
+
def insert(i, *newnodes)
|
471
467
|
(0..@array.length).include? i or
|
472
468
|
raise IndexError, "index #{i} out of NodeList (length #{@array.length})"
|
473
469
|
newnodes = add_prep(newnodes)
|
@@ -476,14 +472,14 @@ module C
|
|
476
472
|
adjust_indices_(i)
|
477
473
|
return self
|
478
474
|
end
|
479
|
-
def <<
|
480
|
-
newnode = *add_prep([newnode])
|
475
|
+
def <<(newnode)
|
476
|
+
newnode, = *add_prep([newnode])
|
481
477
|
@array << newnode
|
482
478
|
added_(newnode)
|
483
479
|
adjust_indices_(@array.length - 1)
|
484
480
|
return self
|
485
481
|
end
|
486
|
-
def []=
|
482
|
+
def []=(*args)
|
487
483
|
newnodes = args.pop
|
488
484
|
i, n, splat = parse_index(*args)
|
489
485
|
oldnodes = @array[i, n] or
|
@@ -491,7 +487,7 @@ module C
|
|
491
487
|
if splat
|
492
488
|
newnodes = add_prep(newnodes, oldnodes)
|
493
489
|
else
|
494
|
-
|
490
|
+
# newnodes is a single node (not an Array)
|
495
491
|
newnodes = add_prep([newnodes], [oldnodes])
|
496
492
|
end
|
497
493
|
@array[i, n] = newnodes
|
@@ -505,7 +501,7 @@ module C
|
|
505
501
|
adjust_indices_(i)
|
506
502
|
return newnodes
|
507
503
|
end
|
508
|
-
def concat
|
504
|
+
def concat(other)
|
509
505
|
other = other.to_a
|
510
506
|
other = add_prep(other)
|
511
507
|
len = @array.length
|
@@ -514,7 +510,7 @@ module C
|
|
514
510
|
adjust_indices_(len)
|
515
511
|
return self
|
516
512
|
end
|
517
|
-
def delete_at
|
513
|
+
def delete_at(index)
|
518
514
|
if index < @array.length
|
519
515
|
ret = @array.delete_at(index)
|
520
516
|
removed_(ret)
|
@@ -530,7 +526,7 @@ module C
|
|
530
526
|
removed_(*nodes)
|
531
527
|
return self
|
532
528
|
end
|
533
|
-
def replace
|
529
|
+
def replace(other)
|
534
530
|
other = other.to_a
|
535
531
|
other = add_prep(other)
|
536
532
|
oldnodes = @array.dup
|
@@ -543,10 +539,10 @@ module C
|
|
543
539
|
end
|
544
540
|
|
545
541
|
class NodeChain
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
def first
|
542
|
+
#
|
543
|
+
# const methods
|
544
|
+
#
|
545
|
+
def first(n=nil)
|
550
546
|
if n.nil?
|
551
547
|
return @first
|
552
548
|
else
|
@@ -560,7 +556,7 @@ module C
|
|
560
556
|
return ret
|
561
557
|
end
|
562
558
|
end
|
563
|
-
def last
|
559
|
+
def last(n=nil)
|
564
560
|
if n.nil?
|
565
561
|
return @last
|
566
562
|
else
|
@@ -602,12 +598,12 @@ module C
|
|
602
598
|
end
|
603
599
|
return ret
|
604
600
|
end
|
605
|
-
def []
|
601
|
+
def [](*args)
|
606
602
|
i, n, splat = parse_index(*args)
|
607
603
|
return nil if i >= @length
|
608
604
|
node = get_(i)
|
609
605
|
if splat
|
610
|
-
|
606
|
+
# return an array of Nodes
|
611
607
|
n = length-i if n > length-i
|
612
608
|
ret = ::Array.new(n) do
|
613
609
|
r = node
|
@@ -616,7 +612,7 @@ module C
|
|
616
612
|
end
|
617
613
|
return ret
|
618
614
|
else
|
619
|
-
|
615
|
+
# return a Node
|
620
616
|
return node
|
621
617
|
end
|
622
618
|
end
|
@@ -627,7 +623,7 @@ module C
|
|
627
623
|
def empty?
|
628
624
|
@length.zero?
|
629
625
|
end
|
630
|
-
def index
|
626
|
+
def index(node)
|
631
627
|
curr = @first
|
632
628
|
i = 0
|
633
629
|
while curr
|
@@ -637,7 +633,7 @@ module C
|
|
637
633
|
end
|
638
634
|
return nil
|
639
635
|
end
|
640
|
-
def rindex
|
636
|
+
def rindex(node)
|
641
637
|
curr = @last
|
642
638
|
i = @length - 1
|
643
639
|
while curr
|
@@ -647,34 +643,34 @@ module C
|
|
647
643
|
end
|
648
644
|
return nil
|
649
645
|
end
|
650
|
-
def values_at
|
646
|
+
def values_at(*args)
|
651
647
|
args.map!{|i| self[i]}
|
652
648
|
end
|
653
|
-
def join
|
649
|
+
def join(*args)
|
654
650
|
self.to_a.join(*args)
|
655
651
|
end
|
656
652
|
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
def push
|
653
|
+
#
|
654
|
+
# non-const methods
|
655
|
+
#
|
656
|
+
def push(*newnodes)
|
661
657
|
newnodes = add_prep(newnodes)
|
662
658
|
added_(*newnodes)
|
663
659
|
link_(@last, newnodes, nil)
|
664
660
|
return self
|
665
661
|
end
|
666
|
-
def <<
|
662
|
+
def <<(newnode)
|
667
663
|
return push(newnode)
|
668
664
|
end
|
669
|
-
def unshift
|
665
|
+
def unshift(*newnodes)
|
670
666
|
newnodes = add_prep(newnodes)
|
671
667
|
added_(*newnodes)
|
672
668
|
link_(nil, newnodes, @first)
|
673
669
|
return self
|
674
670
|
end
|
675
|
-
def pop
|
671
|
+
def pop(n=nil)
|
676
672
|
if n
|
677
|
-
|
673
|
+
# return an Array of Nodes
|
678
674
|
ret = last(n)
|
679
675
|
return ret if ret.empty?
|
680
676
|
link2_(ret.first.instance_variable_get(:@prev), nil)
|
@@ -682,16 +678,16 @@ module C
|
|
682
678
|
return ret
|
683
679
|
else
|
684
680
|
return nil if empty?
|
685
|
-
|
681
|
+
# return a Node
|
686
682
|
ret = @last
|
687
683
|
link2_(@last.instance_variable_get(:@prev), nil)
|
688
684
|
removed_(ret)
|
689
685
|
return ret
|
690
686
|
end
|
691
687
|
end
|
692
|
-
def shift
|
688
|
+
def shift(n=nil)
|
693
689
|
if n
|
694
|
-
|
690
|
+
# return an Array of Nodes
|
695
691
|
ret = first(n)
|
696
692
|
return ret if ret.empty?
|
697
693
|
link2_(nil, ret.last.instance_variable_get(:@next))
|
@@ -699,14 +695,14 @@ module C
|
|
699
695
|
return ret
|
700
696
|
else
|
701
697
|
return nil if empty?
|
702
|
-
|
698
|
+
# return a Node
|
703
699
|
ret = @first
|
704
700
|
link2_(nil, @first.instance_variable_get(:@next))
|
705
701
|
removed_(ret)
|
706
702
|
return ret
|
707
703
|
end
|
708
704
|
end
|
709
|
-
def insert
|
705
|
+
def insert(i, *newnodes)
|
710
706
|
(0..@length).include? i or
|
711
707
|
raise IndexError, "index #{i} out of NodeList"
|
712
708
|
if i == @length
|
@@ -715,7 +711,7 @@ module C
|
|
715
711
|
insert_before(self[i], *newnodes)
|
716
712
|
end
|
717
713
|
end
|
718
|
-
def []=
|
714
|
+
def []=(*args)
|
719
715
|
newnodes = args.pop
|
720
716
|
i, n, splat = parse_index(*args)
|
721
717
|
oldnodes = self[i, n] or
|
@@ -742,10 +738,10 @@ module C
|
|
742
738
|
end
|
743
739
|
return newnodes
|
744
740
|
end
|
745
|
-
def concat
|
741
|
+
def concat(other)
|
746
742
|
return push(*other.to_a)
|
747
743
|
end
|
748
|
-
def delete_at
|
744
|
+
def delete_at(index)
|
749
745
|
node = self[index]
|
750
746
|
remove_node(node)
|
751
747
|
return node
|
@@ -756,15 +752,15 @@ module C
|
|
756
752
|
@length = 0
|
757
753
|
return self
|
758
754
|
end
|
759
|
-
def replace
|
755
|
+
def replace(other)
|
760
756
|
return clear.push(*other.to_a)
|
761
757
|
end
|
762
758
|
|
763
759
|
private
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
def link_
|
760
|
+
#
|
761
|
+
# Link up `nodes' between `a' and `b'.
|
762
|
+
#
|
763
|
+
def link_(a, nodes, b)
|
768
764
|
if nodes.empty?
|
769
765
|
if a.nil?
|
770
766
|
@first = b
|
@@ -777,7 +773,7 @@ module C
|
|
777
773
|
b.instance_variable_set(:@prev, a)
|
778
774
|
end
|
779
775
|
else
|
780
|
-
|
776
|
+
# connect `a' and `b'
|
781
777
|
first = nodes.first
|
782
778
|
if a.nil?
|
783
779
|
@first = first
|
@@ -790,8 +786,8 @@ module C
|
|
790
786
|
else
|
791
787
|
b.instance_variable_set(:@prev, last)
|
792
788
|
end
|
793
|
-
|
794
|
-
|
789
|
+
|
790
|
+
# connect `nodes'
|
795
791
|
if nodes.length == 1
|
796
792
|
node = nodes[0]
|
797
793
|
node.instance_variable_set(:@prev, a)
|
@@ -809,8 +805,10 @@ module C
|
|
809
805
|
end
|
810
806
|
end
|
811
807
|
end
|
812
|
-
|
813
|
-
|
808
|
+
#
|
809
|
+
# Special case for 2
|
810
|
+
#
|
811
|
+
def link2_(a, b)
|
814
812
|
if a.nil?
|
815
813
|
@first = b
|
816
814
|
else
|
@@ -822,17 +820,18 @@ module C
|
|
822
820
|
b.instance_variable_set(:@prev, a) unless b.nil?
|
823
821
|
end
|
824
822
|
end
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
823
|
+
|
824
|
+
#
|
825
|
+
# Return the `i'th Node. Assume `i' is in 0...length.
|
826
|
+
#
|
827
|
+
def get_(i)
|
828
|
+
# return a Node
|
830
829
|
if i < (@length >> 1)
|
831
|
-
|
830
|
+
# go from the beginning
|
832
831
|
node = @first
|
833
832
|
i.times{node = node.next}
|
834
833
|
else
|
835
|
-
|
834
|
+
# go from the end
|
836
835
|
node = @last
|
837
836
|
(@length - 1 - i).times{node = node.prev}
|
838
837
|
end
|