cast 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,8 @@
1
- ###
2
- ### ##################################################################
3
- ###
4
- ### Node#inspect.
5
- ###
6
- ### ##################################################################
7
- ###
1
+ ######################################################################
2
+ #
3
+ # Node#inspect.
4
+ #
5
+ ######################################################################
8
6
 
9
7
  module C
10
8
  class Node
@@ -13,7 +11,7 @@ module C
13
11
  return Node.inspect1(self)
14
12
  end
15
13
 
16
- def Node.inspect1 x, prefix='', indent=0, is_child=true
14
+ def Node.inspect1(x, prefix='', indent=0, is_child=true)
17
15
  case x
18
16
  when NodeList
19
17
  if x.empty?
@@ -42,8 +40,8 @@ module C
42
40
  others.each do |field|
43
41
  val = x.send(field.reader)
44
42
  next if val == field.make_default ||
45
- ## don't bother with non-child Nodes, since they may cause
46
- ## loops in the tree
43
+ # don't bother with non-child Nodes, since they may cause
44
+ # loops in the tree
47
45
  (val.is_a?(Node) && !field.child?)
48
46
  str << inspect1(val, "#{field.reader}: ", indent+1, field.child?)
49
47
  end
@@ -1,26 +1,18 @@
1
- ###
2
- ### ##################################################################
3
- ###
4
- ### Node core functionality.
5
- ###
6
- ### ##################################################################
7
- ###
1
+ ######################################################################
2
+ #
3
+ # Node core functionality.
4
+ #
5
+ ######################################################################
8
6
 
9
7
  module C
10
- ###
11
- ### ================================================================
12
- ###
13
- ### Node
14
- ###
15
- ### Abstract base class for all AST nodes.
16
- ###
17
- ### ================================================================
18
- ###
8
+ #
9
+ # Abstract base class for all AST nodes.
10
+ #
19
11
  class Node
20
- ###
21
- ### Called by the test suite to ensure all invariants are true.
22
- ###
23
- def assert_invariants testcase
12
+ #
13
+ # Called by the test suite to ensure all invariants are true.
14
+ #
15
+ def assert_invariants(testcase)
24
16
  fields.each do |field|
25
17
  if val = send(field.reader)
26
18
  assert_same(self, node.parent, "field.reader is #{field.reader}")
@@ -30,19 +22,21 @@ module C
30
22
  end
31
23
  end
32
24
  end
33
- ###
34
- ### Like self.new, but the first argument is taken as the position
35
- ### of the Node.
36
- ###
37
- def self.new_at pos, *args
25
+
26
+ #
27
+ # Like self.new, but the first argument is taken as the position
28
+ # of the Node.
29
+ #
30
+ def self.new_at(pos, *args)
38
31
  ret = new(*args)
39
32
  ret.pos = pos
40
33
  return ret
41
34
  end
42
- ###
43
- ### True iff both are of the same class, and all fields are #==.
44
- ###
45
- def == other
35
+
36
+ #
37
+ # True iff both are of the same class, and all fields are #==.
38
+ #
39
+ def ==(other)
46
40
  return false if !other.is_a? self.class
47
41
 
48
42
  fields.all? do |field|
@@ -51,25 +45,27 @@ module C
51
45
  mine == yours
52
46
  end
53
47
  end
54
- ###
55
- ### Same as #==.
56
- ###
57
- def eql? other
48
+
49
+ #
50
+ # Same as #==.
51
+ #
52
+ def eql?(other)
58
53
  return self == other
59
54
  end
60
- ###
61
- ### #hash, as defined in Object.
62
- ###
55
+
56
+ #
57
+ # #hash, as defined in Object.
58
+ #
63
59
  def hash
64
60
  fields.inject(0) do |hash, field|
65
61
  val = send(field.reader)
66
62
  hash ^= val.hash
67
63
  end
68
64
  end
69
- ###
70
- ### As defined for ::Object, but children are recursively
71
- ### `#dup'ed.
72
- ###
65
+
66
+ #
67
+ # As defined for ::Object, but children are recursively `#dup'ed.
68
+ #
73
69
  def dup
74
70
  ret = super
75
71
  ret.instance_variable_set(:@parent, nil)
@@ -82,10 +78,10 @@ module C
82
78
  end
83
79
  return ret
84
80
  end
85
- ###
86
- ### As defined for ::Object, but children are recursively
87
- ### `#clone'd.
88
- ###
81
+
82
+ #
83
+ # As defined for ::Object, but children are recursively `#clone'd.
84
+ #
89
85
  def clone
90
86
  ret = super
91
87
  ret.instance_variable_set(:@parent, nil)
@@ -99,18 +95,16 @@ module C
99
95
  return ret
100
96
  end
101
97
 
102
- ###
103
- ### --------------------------------------------------------------
104
- ### Tree traversal
105
- ### --------------------------------------------------------------
106
- ###
98
+ # ----------------------------------------------------------------
99
+ # Tree traversal
100
+ # ----------------------------------------------------------------
107
101
 
108
102
  include Enumerable
109
103
 
110
- ###
111
- ### Yield each child in field order.
112
- ###
113
- def each &blk
104
+ #
105
+ # Yield each child in field order.
106
+ #
107
+ def each(&blk)
114
108
  fields.each do |field|
115
109
  if field.child?
116
110
  val = self.send(field.reader)
@@ -119,10 +113,11 @@ module C
119
113
  end
120
114
  return self
121
115
  end
122
- ###
123
- ### Yield each child in reverse field order.
124
- ###
125
- def reverse_each &blk
116
+
117
+ #
118
+ # Yield each child in reverse field order.
119
+ #
120
+ def reverse_each(&blk)
126
121
  fields.reverse_each do |field|
127
122
  if field.child?
128
123
  val = self.send(field.reader)
@@ -131,335 +126,351 @@ module C
131
126
  end
132
127
  return self
133
128
  end
134
- ###
135
- ### Perform a depth-first walk of the AST, yielding on recursively
136
- ### on each child node:
137
- ###
138
- ### - (:descending, node) just prior to descending into `node'
139
- ### - (:ascending, node) just after ascending from `node'
140
- ###
141
- ### If the block throws :prune while descending, the children of
142
- ### the node that was passed to that block will not be visited.
143
- ###
144
- def depth_first &blk
129
+
130
+ #
131
+ # Perform a depth-first walk of the AST, yielding on recursively
132
+ # on each child node:
133
+ #
134
+ # - (:descending, node) just prior to descending into `node'
135
+ # - (:ascending, node) just after ascending from `node'
136
+ #
137
+ # If the block throws :prune while descending, the children of the
138
+ # node that was passed to that block will not be visited.
139
+ #
140
+ def depth_first(&blk)
145
141
  catch :prune do
146
142
  yield :descending, self
147
- each{|n| n.depth_first &blk}
143
+ each{|n| n.depth_first(&blk)}
148
144
  end
149
145
  yield :ascending, self
150
146
  return self
151
147
  end
152
- ###
153
- ### Perform a reverse depth-first walk of the AST, yielding on
154
- ### each node:
155
- ###
156
- ### - (:descending, node) just prior to descending into `node'
157
- ### - (:ascending, node) just after ascending from `node'
158
- ###
159
- ### If the block throws :prune while descending, the children of
160
- ### the node that was passed to that block will not be visited.
161
- ###
162
- def reverse_depth_first &blk
148
+
149
+ #
150
+ # Perform a reverse depth-first walk of the AST, yielding on each
151
+ # node:
152
+ #
153
+ # - (:descending, node) just prior to descending into `node'
154
+ # - (:ascending, node) just after ascending from `node'
155
+ #
156
+ # If the block throws :prune while descending, the children of the
157
+ # node that was passed to that block will not be visited.
158
+ #
159
+ def reverse_depth_first(&blk)
163
160
  catch :prune do
164
161
  yield :descending, self
165
- reverse_each{|n| n.reverse_depth_first &blk}
162
+ reverse_each{|n| n.reverse_depth_first(&blk)}
166
163
  end
167
164
  yield :ascending, self
168
165
  return self
169
166
  end
170
- ###
171
- ### Perform a preorder walk of the AST, yielding each node in
172
- ### turn. Return self.
173
- ###
174
- ### If the block throws :prune, the children of the node that was
175
- ### passed to that block will not be visited.
176
- ###
177
- def preorder &blk
167
+
168
+ #
169
+ # Perform a preorder walk of the AST, yielding each node in turn.
170
+ # Return self.
171
+ #
172
+ # If the block throws :prune, the children of the node that was
173
+ # passed to that block will not be visited.
174
+ #
175
+ def preorder(&blk)
178
176
  catch :prune do
179
177
  yield self
180
- each{|n| n.preorder &blk}
178
+ each{|n| n.preorder(&blk)}
181
179
  end
182
180
  return self
183
181
  end
184
- ###
185
- ### Perform a reverse preorder walk of the AST, yielding each node
186
- ### in turn. Return self.
187
- ###
188
- ### If the block throws :prune, the children of the node that was
189
- ### passed to that block will not be visited.
190
- ###
191
- def reverse_preorder &blk
182
+
183
+ #
184
+ # Perform a reverse preorder walk of the AST, yielding each node
185
+ # in turn. Return self.
186
+ #
187
+ # If the block throws :prune, the children of the node that was
188
+ # passed to that block will not be visited.
189
+ #
190
+ def reverse_preorder(&blk)
192
191
  catch :prune do
193
192
  yield self
194
- reverse_each{|n| n.reverse_preorder &blk}
193
+ reverse_each{|n| n.reverse_preorder(&blk)}
195
194
  end
196
195
  return self
197
196
  end
198
- ###
199
- ### Perform a postorder walk of the AST, yielding each node in
200
- ### turn. Return self.
201
- ###
202
- def postorder &blk
203
- each{|n| n.postorder &blk}
197
+
198
+ #
199
+ # Perform a postorder walk of the AST, yielding each node in turn.
200
+ # Return self.
201
+ #
202
+ def postorder(&blk)
203
+ each{|n| n.postorder(&blk)}
204
204
  yield self
205
205
  return self
206
206
  end
207
- ###
208
- ### Perform a reverse postorder walk of the AST, yielding each
209
- ### node in turn. Return self.
210
- ###
211
- def reverse_postorder &blk
212
- reverse_each{|n| n.reverse_postorder &blk}
207
+
208
+ #
209
+ # Perform a reverse postorder walk of the AST, yielding each node
210
+ # in turn. Return self.
211
+ #
212
+ def reverse_postorder(&blk)
213
+ reverse_each{|n| n.reverse_postorder(&blk)}
213
214
  yield self
214
215
  return self
215
216
  end
216
217
 
217
- ###
218
- ### --------------------------------------------------------------
219
- ### Node tree-structure methods
220
- ### --------------------------------------------------------------
221
- ###
218
+ # ----------------------------------------------------------------
219
+ # Node tree-structure methods
220
+ # ----------------------------------------------------------------
222
221
 
223
222
  class BadParent < StandardError; end
224
223
  class NoParent < BadParent; end
225
224
 
226
- ###
227
- ### The Node's parent.
228
- ###
225
+ #
226
+ # The Node's parent.
227
+ #
229
228
  attr_accessor :parent
230
229
  private :parent=
231
- ###
232
- ### The position in the source file the construct this node
233
- ### represents appears at.
234
- ###
230
+
231
+ #
232
+ # The position in the source file the construct this node
233
+ # represents appears at.
234
+ #
235
235
  attr_accessor :pos
236
- ###
237
- ### Return the sibling Node that comes after this in preorder
238
- ### sequence.
239
- ###
240
- ### Raises NoParent if there's no parent.
241
- ###
236
+
237
+ #
238
+ # Return the sibling Node that comes after this in preorder
239
+ # sequence.
240
+ #
241
+ # Raises NoParent if there's no parent.
242
+ #
242
243
  def next
243
244
  @parent or raise NoParent
244
245
  return @parent.node_after(self)
245
246
  end
246
- ###
247
- ### Return the sibling Node that comes after this in the parent
248
- ### NodeList.
249
- ###
250
- ### Raises:
251
- ### -- NoParent if there's no parent
252
- ### -- BadParent if the parent is otherwise not a NodeList
253
- ###
247
+
248
+ #
249
+ # Return the sibling Node that comes after this in the parent
250
+ # NodeList.
251
+ #
252
+ # Raises:
253
+ # -- NoParent if there's no parent
254
+ # -- BadParent if the parent is otherwise not a NodeList
255
+ #
254
256
  def list_next
255
257
  @parent or raise NoParent
256
258
  @parent.NodeList? or raise BadParent
257
259
  return @parent.node_after(self)
258
260
  end
259
- ###
260
- ### Return the sibling Node that comes before this in preorder
261
- ### sequence.
262
- ###
263
- ### Raises NoParent if there's no parent.
264
- ###
261
+
262
+ #
263
+ # Return the sibling Node that comes before this in preorder
264
+ # sequence.
265
+ #
266
+ # Raises NoParent if there's no parent.
267
+ #
265
268
  def prev
266
269
  @parent or raise NoParent
267
270
  return @parent.node_before(self)
268
271
  end
269
- ###
270
- ### Return the sibling Node that comes before this in the parent
271
- ### NodeList.
272
- ###
273
- ### Raises:
274
- ### -- NoParent if there's no parent
275
- ### -- BadParent if the parent is otherwise not a NodeList
276
- ###
272
+
273
+ #
274
+ # Return the sibling Node that comes before this in the parent
275
+ # NodeList.
276
+ #
277
+ # Raises:
278
+ # -- NoParent if there's no parent
279
+ # -- BadParent if the parent is otherwise not a NodeList
280
+ #
277
281
  def list_prev
278
282
  @parent or raise NoParent
279
283
  @parent.NodeList? or raise BadParent
280
284
  return @parent.node_before(self)
281
285
  end
282
- ###
283
- ### Detach this Node from the tree and return it.
284
- ###
285
- ### Raises NoParent if there's no parent.
286
- ###
286
+
287
+ #
288
+ # Detach this Node from the tree and return it.
289
+ #
290
+ # Raises NoParent if there's no parent.
291
+ #
287
292
  def detach
288
293
  @parent or raise NoParent
289
294
  @parent.remove_node(self)
290
295
  return self
291
296
  end
292
- ###
293
- ### Replace this Node in the tree with the given node(s). Return
294
- ### this node.
295
- ###
296
- ### Raises:
297
- ### -- NoParent if there's no parent
298
- ### -- BadParent if the parent is otherwise not a NodeList, and
299
- ### more than one node is given.
300
- ###
301
- def replace_with *nodes
297
+
298
+ #
299
+ # Replace this Node in the tree with the given node(s). Return
300
+ # this node.
301
+ #
302
+ # Raises:
303
+ # -- NoParent if there's no parent
304
+ # -- BadParent if the parent is otherwise not a NodeList, and
305
+ # more than one node is given.
306
+ #
307
+ def replace_with(*nodes)
302
308
  @parent or raise NoParent
303
309
  @parent.replace_node(self, *nodes)
304
310
  return self
305
311
  end
306
- ###
307
- ### Swap this node with `node' in their trees. If either node is
308
- ### detached, the other will become detached as a result of
309
- ### calling this method.
310
- ###
312
+
313
+ #
314
+ # Swap this node with `node' in their trees. If either node is
315
+ # detached, the other will become detached as a result of calling
316
+ # this method.
317
+ #
311
318
  def swap_with node
312
319
  return self if node.equal? self
313
320
  if self.attached?
314
321
  if node.attached?
315
- ## both attached -- use placeholder
322
+ # both attached -- use placeholder
316
323
  placeholder = Default.new
317
324
  my_parent = @parent
318
325
  my_parent.replace_node(self, placeholder)
319
326
  node.parent.replace_node(node, self)
320
327
  my_parent.replace_node(placeholder, node)
321
328
  else
322
- ## only `self' attached
329
+ # only `self' attached
323
330
  @parent.replace_node(self, node)
324
331
  end
325
332
  else
326
333
  if node.attached?
327
- ## only `node' attached
334
+ # only `node' attached
328
335
  node.parent.replace_node(node, self)
329
336
  else
330
- ## neither attached -- nothing to do
337
+ # neither attached -- nothing to do
331
338
  end
332
339
  end
333
340
  return self
334
341
  end
335
- ###
336
- ### Insert `newnodes' before this node. Return this node.
337
- ###
338
- ### Raises:
339
- ### -- NoParent if there's no parent
340
- ### -- BadParent if the parent is otherwise not a NodeList
341
- ###
342
- def insert_prev *newnodes
342
+
343
+ #
344
+ # Insert `newnodes' before this node. Return this node.
345
+ #
346
+ # Raises:
347
+ # -- NoParent if there's no parent
348
+ # -- BadParent if the parent is otherwise not a NodeList
349
+ #
350
+ def insert_prev(*newnodes)
343
351
  @parent or raise NoParent
344
352
  @parent.NodeList? or raise BadParent
345
353
  @parent.insert_before(self, *newnodes)
346
354
  return self
347
355
  end
348
- ###
349
- ### Insert `newnodes' after this node. Return this node.
350
- ###
351
- ### Raises:
352
- ### -- NoParent if there's no parent
353
- ### -- BadParent if the parent is otherwise not a NodeList
354
- ###
355
- def insert_next *newnodes
356
+
357
+ #
358
+ # Insert `newnodes' after this node. Return this node.
359
+ #
360
+ # Raises:
361
+ # -- NoParent if there's no parent
362
+ # -- BadParent if the parent is otherwise not a NodeList
363
+ #
364
+ def insert_next(*newnodes)
356
365
  @parent or raise NoParent
357
366
  @parent.NodeList? or raise BadParent
358
367
  @parent.insert_after(self, *newnodes)
359
368
  return self
360
369
  end
361
- ###
362
- ### Return true if this Node is detached (i.e., #parent is nil),
363
- ### false otherwise.
364
- ###
365
- ### This is equal to !attached?
366
- ###
370
+
371
+ #
372
+ # Return true if this Node is detached (i.e., #parent is nil),
373
+ # false otherwise.
374
+ #
375
+ # This is equal to !attached?
376
+ #
367
377
  def detached?
368
378
  @parent.nil?
369
379
  end
370
- ###
371
- ### Return true if this Node is attached (i.e., #parent is
372
- ### nonnil), false otherwise.
373
- ###
374
- ### This is equal to !detached?
375
- ###
380
+
381
+ #
382
+ # Return true if this Node is attached (i.e., #parent is nonnil),
383
+ # false otherwise.
384
+ #
385
+ # This is equal to !detached?
386
+ #
376
387
  def attached?
377
388
  !@parent.nil?
378
389
  end
379
390
 
380
- ###
381
- ### --------------------------------------------------------------
382
- ### Subclass management
383
- ### --------------------------------------------------------------
384
- ###
391
+ # ----------------------------------------------------------------
392
+ # Subclass management
393
+ # ----------------------------------------------------------------
385
394
 
386
- ###
387
- ### The direct subclasses of this class (an Array of Class).
388
- ###
395
+ #
396
+ # The direct subclasses of this class (an Array of Class).
397
+ #
389
398
  attr_reader :subclasses
390
- ###
391
- ### Return all classes which have this class somewhere in its
392
- ### ancestry (an Array of Class).
393
- ###
399
+
400
+ #
401
+ # Return all classes which have this class somewhere in its
402
+ # ancestry (an Array of Class).
403
+ #
394
404
  def self.subclasses_recursive
395
405
  ret = @subclasses.dup
396
406
  @subclasses.each{|c| ret.concat(c.subclasses_recursive)}
397
407
  return ret
398
408
  end
399
- ###
400
- ### Callback defined in Class.
401
- ###
402
- def self.inherited klass
409
+
410
+ #
411
+ # Callback defined in Class.
412
+ #
413
+ def self.inherited(klass)
403
414
  @subclasses << klass
404
415
  klass.instance_variable_set(:@subclasses, [])
405
416
  klass.instance_variable_set(:@fields , [])
406
417
  end
407
- ###
408
- ### Declare this class as abstract.
409
- ###
418
+
419
+ #
420
+ # Declare this class as abstract.
421
+ #
410
422
  def self.abstract
411
423
  end
412
424
 
413
- ## set the instance vars for Node
425
+ # set the instance vars for Node
414
426
  @subclasses = []
415
427
  @fields = []
416
428
 
417
- ###
418
- ### --------------------------------------------------------------
419
- ###
420
- ### Fields
421
- ###
422
- ### Fields are interesting attributes, that are, e.g., compared in
423
- ### `==', and copied in `dup' and `clone'. "Child" fields are
424
- ### also yielded in a traversal. For each field, a setter and
425
- ### getter is created, and the corresponding instance variable is
426
- ### set in `initialize'.
427
- ###
428
- ### Child fields are declared using Node.child; other fields are
429
- ### declared using Node.field.
430
- ###
431
- ### --------------------------------------------------------------
432
- ###
429
+ # --------------------------------------------------------------
430
+ #
431
+ # Fields
432
+ #
433
+ # Fields are interesting attributes, that are, e.g., compared in
434
+ # `==', and copied in `dup' and `clone'. "Child" fields are also
435
+ # yielded in a traversal. For each field, a setter and getter is
436
+ # created, and the corresponding instance variable is set in
437
+ # `initialize'.
438
+ #
439
+ # Child fields are declared using Node.child; other fields are
440
+ # declared using Node.field.
441
+ #
442
+ # --------------------------------------------------------------
433
443
 
434
444
  private # -------------------------------------------------------
435
445
 
436
- ###
437
- ### Add the Field `newfield' to the list of fields for this class.
438
- ###
439
- def self.add_field newfield
440
- ## add the newfield to @fields, and set the index
446
+ #
447
+ # Add the Field `newfield' to the list of fields for this class.
448
+ #
449
+ def self.add_field(newfield)
450
+ # add the newfield to @fields, and set the index
441
451
  fields = @fields
442
452
  newfield.index = fields.length
443
453
  fields << newfield
444
- ## getter
445
- define_method(newfield.reader) do
446
- instance_variable_get(newfield.var)
447
- end
448
- ## setter
454
+ # getter
455
+ # define_method(newfield.reader) do
456
+ # instance_variable_get(newfield.var)
457
+ # end
458
+ eval "def #{newfield.reader}; #{newfield.var}; end"
459
+ # setter
449
460
  if newfield.child?
450
461
  define_method(newfield.writer) do |val|
451
462
  old = send(newfield.reader)
452
463
  return if val.equal? old
453
- ## detach the old Node
464
+ # detach the old Node
454
465
  old = self.send(newfield.reader)
455
466
  unless old.nil?
456
467
  old.instance_variable_set(:@parent, nil)
457
468
  end
458
- ## copy val if needed
469
+ # copy val if needed
459
470
  val = val.clone if !val.nil? && val.attached?
460
- ## set
471
+ # set
461
472
  self.instance_variable_set(newfield.var, val)
462
- ## attach the new Node
473
+ # attach the new Node
463
474
  unless val.nil?
464
475
  val.instance_variable_set(:@parent, self)
465
476
  val.instance_variable_set(:@parent_field, newfield)
@@ -470,56 +481,51 @@ module C
470
481
  instance_variable_set(newfield.var, val)
471
482
  end
472
483
  end
484
+ public newfield.reader, newfield.writer
473
485
  end
474
486
  def self.fields
475
487
  @fields
476
488
  end
477
- ###
478
- ### The args are the fields/children in the order they were
479
- ### declared, all optional. If the last argument is a hash, field
480
- ### and child values are looked up in there. If a value is given
481
- ### by both argument and hash, the behaviour is undefined.
482
- ###
483
-
484
- ###
485
- ### Define an initialize method. The initialize method sets the
486
- ### fields named in `syms' from the arguments given to it. The
487
- ### initialize method also takes named parameters (i.e., an
488
- ### optional Hash as the last argument), which may be used to set
489
- ### fields not even named in `syms'. The syms in the optional
490
- ### Hash are the values of the `init_key' members of the
491
- ### corresponding Field objects.
492
- ###
493
- ### As an example for this Node class:
494
- ###
495
- ### class X < Node
496
- ### field :x
497
- ### field :y
498
- ### child :z
499
- ### initializer :z, :y
500
- ### end
501
- ###
502
- ### ...X.new can be called in any of these ways:
503
- ###
504
- ### X.new # all fields set to default
505
- ### X.new(1) # .z = 1
506
- ### X.new(1, 2) # .z = 1, .y = 2
507
- ### X.new(:x = 1, :y => 2, :z => 3) # .x = 1, .y = 2, .z = 3
508
- ### X.new(1, :x => 2) # .z = 1, .x = 2
509
- ### X.new(1, :z => 2) # undefined behaviour!
510
- ### ...etc.
511
- ###
512
- def self.initializer *syms
489
+
490
+ #
491
+ # Define an initialize method. The initialize method sets the
492
+ # fields named in `syms' from the arguments given to it. The
493
+ # initialize method also takes named parameters (i.e., an optional
494
+ # Hash as the last argument), which may be used to set fields not
495
+ # even named in `syms'. The syms in the optional Hash are the
496
+ # values of the `init_key' members of the corresponding Field
497
+ # objects.
498
+ #
499
+ # As an example for this Node class:
500
+ #
501
+ # class X < Node
502
+ # field :x
503
+ # field :y
504
+ # child :z
505
+ # initializer :z, :y
506
+ # end
507
+ #
508
+ # ...X.new can be called in any of these ways:
509
+ #
510
+ # X.new # all fields set to default
511
+ # X.new(1) # .z = 1
512
+ # X.new(1, 2) # .z = 1, .y = 2
513
+ # X.new(:x = 1, :y => 2, :z => 3) # .x = 1, .y = 2, .z = 3
514
+ # X.new(1, :x => 2) # .z = 1, .x = 2
515
+ # X.new(1, :z => 2) # undefined behaviour!
516
+ # ...etc.
517
+ #
518
+ def self.initializer(*syms)
513
519
  define_method(:initialize) do |*args|
514
- ## pop off the opts hash
520
+ # pop off the opts hash
515
521
  opts = args.last.is_a?(::Hash) ? args.pop : {}
516
522
 
517
- ## add positional args to opts
523
+ # add positional args to opts
518
524
  args.each_with_index do |arg, i|
519
525
  opts[syms[i]] = arg
520
526
  end
521
527
 
522
- ## set field values
528
+ # set field values
523
529
  fields.each do |field|
524
530
  key = field.init_key
525
531
  if opts.key?(key)
@@ -529,7 +535,7 @@ module C
529
535
  end
530
536
  end
531
537
 
532
- ## pos, parent
538
+ # pos, parent
533
539
  @pos = nil
534
540
  @parent = nil
535
541
  end
@@ -537,10 +543,10 @@ module C
537
543
 
538
544
  public # --------------------------------------------------------
539
545
 
540
- ###
541
- ### Declare a field with the given name and default value.
542
- ###
543
- def self.field name, default=:'no default'
546
+ #
547
+ # Declare a field with the given name and default value.
548
+ #
549
+ def self.field(name, default=:'no default')
544
550
  if default == :'no default'
545
551
  if name.to_s[-1] == ??
546
552
  default = false
@@ -549,8 +555,8 @@ module C
549
555
  end
550
556
  end
551
557
 
552
- ## if the field exists, just update its default, otherwise, add
553
- ## a new field
558
+ # if the field exists, just update its default, otherwise, add
559
+ # a new field
554
560
  self.fields.each do |field|
555
561
  if field.reader == name
556
562
  field.default = default
@@ -559,26 +565,28 @@ module C
559
565
  end
560
566
  add_field Field.new(name, default)
561
567
  end
562
- ###
563
- ### Declare a child with the given name and default value. The
564
- ### default value is cloned when used (unless cloning is
565
- ### unnecessary).
566
- ###
567
- def self.child name, default=nil
568
+
569
+ #
570
+ # Declare a child with the given name and default value. The
571
+ # default value is cloned when used (unless cloning is
572
+ # unnecessary).
573
+ #
574
+ def self.child(name, default=nil)
568
575
  field = Field.new(name, default)
569
576
  field.child = true
570
577
  add_field field
571
578
  end
572
- ###
573
- ### Return the list of fields this object has. Don't modify the
574
- ### returned array!
575
- ###
579
+
580
+ #
581
+ # Return the list of fields this object has. Don't modify the
582
+ # returned array!
583
+ #
576
584
  def fields
577
585
  self.class.fields
578
586
  end
579
587
 
580
- def method_missing meth, *args, &blk
581
- ## respond to `Module?'
588
+ def method_missing(meth, *args, &blk)
589
+ # respond to `Module?'
582
590
  methstr = meth.to_s
583
591
  if methstr =~ /^([A-Z].*)\?$/ && C.const_defined?($1)
584
592
  klass = C.const_get($1)
@@ -595,21 +603,17 @@ module C
595
603
  end
596
604
  end
597
605
 
598
- ###
599
- ### ==============================================================
600
- ###
601
- ### Child management
602
- ###
603
- ### ==============================================================
604
- ###
606
+ # ----------------------------------------------------------------
607
+ # Child management
608
+ # ----------------------------------------------------------------
605
609
 
606
610
  public # --------------------------------------------------------
607
611
 
608
- ###
609
- ### Return the Node that comes after the given Node in tree
610
- ### preorder.
611
- ###
612
- def node_after node
612
+ #
613
+ # Return the Node that comes after the given Node in tree
614
+ # preorder.
615
+ #
616
+ def node_after(node)
613
617
  node.parent.equal? self or
614
618
  raise ArgumentError, "node is not a child"
615
619
  fields = self.fields
@@ -622,11 +626,12 @@ module C
622
626
  end
623
627
  return nil
624
628
  end
625
- ###
626
- ### Return the Node that comes before the given Node in tree
627
- ### preorder.
628
- ###
629
- def node_before node
629
+
630
+ #
631
+ # Return the Node that comes before the given Node in tree
632
+ # preorder.
633
+ #
634
+ def node_before(node)
630
635
  node.parent.equal? self or
631
636
  raise ArgumentError, "node is not a child"
632
637
  fields = self.fields
@@ -639,10 +644,11 @@ module C
639
644
  end
640
645
  return nil
641
646
  end
642
- ###
643
- ### Remove the given Node.
644
- ###
645
- def remove_node node
647
+
648
+ #
649
+ # Remove the given Node.
650
+ #
651
+ def remove_node(node)
646
652
  node.parent.equal? self or
647
653
  raise ArgumentError, "node is not a child"
648
654
  field = node.instance_variable_get(:@parent_field)
@@ -651,10 +657,11 @@ module C
651
657
  self.instance_variable_set(field.var, nil)
652
658
  return self
653
659
  end
654
- ###
655
- ### Replace `node' with `newnode'.
656
- ###
657
- def replace_node node, newnode=nil
660
+
661
+ #
662
+ # Replace `node' with `newnode'.
663
+ #
664
+ def replace_node(node, newnode=nil)
658
665
  node.parent.equal? self or
659
666
  raise ArgumentError, "node is not a child"
660
667
  field = node.instance_variable_get(:@parent_field)
@@ -662,13 +669,9 @@ module C
662
669
  return self
663
670
  end
664
671
 
665
- ###
666
- ### ==============================================================
667
- ###
668
- ### Node::Field
669
- ###
670
- ### ==============================================================
671
- ###
672
+ # ----------------------------------------------------------------
673
+ # Node::Field
674
+ # ----------------------------------------------------------------
672
675
 
673
676
  private # -------------------------------------------------------
674
677
 
@@ -676,18 +679,19 @@ module C
676
679
  attr_accessor :var, :reader, :writer, :init_key, :index,
677
680
  :default
678
681
 
679
- ###
680
- ### True if this field is a child field, false otherwise.
681
- ###
682
+ #
683
+ # True if this field is a child field, false otherwise.
684
+ #
682
685
  attr_writer :child
683
686
  def child?
684
687
  @child
685
688
  end
686
- ###
687
- ### Create a default value for this field. This differs from
688
- ### #default in that if it's a Proc, it is called and the result
689
- ### returned.
690
- ###
689
+
690
+ #
691
+ # Create a default value for this field. This differs from
692
+ # #default in that if it's a Proc, it is called and the result
693
+ # returned.
694
+ #
691
695
  def make_default
692
696
  if @default.respond_to? :call
693
697
  @default.call
@@ -696,7 +700,7 @@ module C
696
700
  end
697
701
  end
698
702
 
699
- def initialize name, default
703
+ def initialize(name, default)
700
704
  name = name.to_s
701
705
 
702
706
  @child = false
@@ -710,22 +714,15 @@ module C
710
714
  end
711
715
  end
712
716
 
713
- ###
714
- ### ==============================================================
715
- ###
716
- ### Node::Pos
717
- ###
718
- ### A position in a source file. All Nodes may have one in
719
- ### their #pos attribute.
720
- ###
721
- ### ==============================================================
722
- ###
723
-
724
717
  public # -------------------------------------------------------
725
718
 
719
+ #
720
+ # A position in a source file. All Nodes may have one in their
721
+ # #pos attribute.
722
+ #
726
723
  class Pos
727
724
  attr_accessor :filename, :line_num, :col_num
728
- def initialize filename, line_num, col_num
725
+ def initialize(filename, line_num, col_num)
729
726
  @filename = filename
730
727
  @line_num = line_num
731
728
  @col_num = col_num
@@ -733,7 +730,7 @@ module C
733
730
  def to_s
734
731
  (@filename ? "#@filename:" : '') << "#@line_num:#@col_num"
735
732
  end
736
- def <=> x
733
+ def <=>(x)
737
734
  return nil if self.filename != x.filename
738
735
  return (self.line_num <=> x.line_num).nonzero? ||
739
736
  self.col_num <=> x.col_num