cast 0.0.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,744 +0,0 @@
1
- ###
2
- ### ##################################################################
3
- ###
4
- ### Node core functionality.
5
- ###
6
- ### ##################################################################
7
- ###
8
-
9
- module C
10
- ###
11
- ### ================================================================
12
- ###
13
- ### Node
14
- ###
15
- ### Abstract base class for all AST nodes.
16
- ###
17
- ### ================================================================
18
- ###
19
- class Node
20
- ###
21
- ### Called by the test suite to ensure all invariants are true.
22
- ###
23
- def assert_invariants testcase
24
- fields.each do |field|
25
- if val = send(field.reader)
26
- assert_same(self, node.parent, "field.reader is #{field.reader}")
27
- if field.child?
28
- assert_same(field, val.instance_variable_get(:@parent_field), "field.reader is #{field.reader}")
29
- end
30
- end
31
- end
32
- 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
38
- ret = new(*args)
39
- ret.pos = pos
40
- return ret
41
- end
42
- ###
43
- ### True iff both are of the same class, and all fields are #==.
44
- ###
45
- def == other
46
- return false if !other.is_a? self.class
47
-
48
- fields.all? do |field|
49
- mine = self .send(field.reader)
50
- yours = other.send(field.reader)
51
- mine == yours
52
- end
53
- end
54
- ###
55
- ### Same as #==.
56
- ###
57
- def eql? other
58
- return self == other
59
- end
60
- ###
61
- ### #hash, as defined in Object.
62
- ###
63
- def hash
64
- fields.inject(0) do |hash, field|
65
- val = send(field.reader)
66
- hash ^= val.hash
67
- end
68
- end
69
- ###
70
- ### As defined for ::Object, but children are recursively
71
- ### `#dup'ed.
72
- ###
73
- def dup
74
- ret = super
75
- ret.instance_variable_set(:@parent, nil)
76
- fields.each do |field|
77
- next if !field.child?
78
- val = instance_variable_get(field.var)
79
- val = val.dup unless val.nil?
80
- ret.instance_variable_set(field.var, nil)
81
- ret.send(field.writer, val)
82
- end
83
- return ret
84
- end
85
- ###
86
- ### As defined for ::Object, but children are recursively
87
- ### `#clone'd.
88
- ###
89
- def clone
90
- ret = super
91
- ret.instance_variable_set(:@parent, nil)
92
- fields.each do |field|
93
- next if !field.child?
94
- val = instance_variable_get(field.var)
95
- val = val.clone unless val.nil?
96
- ret.instance_variable_set(field.var, nil)
97
- ret.send(field.writer, val)
98
- end
99
- return ret
100
- end
101
-
102
- ###
103
- ### --------------------------------------------------------------
104
- ### Tree traversal
105
- ### --------------------------------------------------------------
106
- ###
107
-
108
- include Enumerable
109
-
110
- ###
111
- ### Yield each child in field order.
112
- ###
113
- def each &blk
114
- fields.each do |field|
115
- if field.child?
116
- val = self.send(field.reader)
117
- yield val unless val.nil?
118
- end
119
- end
120
- return self
121
- end
122
- ###
123
- ### Yield each child in reverse field order.
124
- ###
125
- def reverse_each &blk
126
- fields.reverse_each do |field|
127
- if field.child?
128
- val = self.send(field.reader)
129
- yield val unless val.nil?
130
- end
131
- end
132
- return self
133
- 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
145
- catch :prune do
146
- yield :descending, self
147
- each{|n| n.depth_first &blk}
148
- end
149
- yield :ascending, self
150
- return self
151
- 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
163
- catch :prune do
164
- yield :descending, self
165
- reverse_each{|n| n.reverse_depth_first &blk}
166
- end
167
- yield :ascending, self
168
- return self
169
- 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
178
- catch :prune do
179
- yield self
180
- each{|n| n.preorder &blk}
181
- end
182
- return self
183
- 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
192
- catch :prune do
193
- yield self
194
- reverse_each{|n| n.reverse_preorder &blk}
195
- end
196
- return self
197
- 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}
204
- yield self
205
- return self
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}
213
- yield self
214
- return self
215
- end
216
-
217
- ###
218
- ### --------------------------------------------------------------
219
- ### Node tree-structure methods
220
- ### --------------------------------------------------------------
221
- ###
222
-
223
- class BadParent < StandardError; end
224
- class NoParent < BadParent; end
225
-
226
- ###
227
- ### The Node's parent.
228
- ###
229
- attr_accessor :parent
230
- private :parent=
231
- ###
232
- ### The position in the source file the construct this node
233
- ### represents appears at.
234
- ###
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
- ###
242
- def next
243
- @parent or raise NoParent
244
- return @parent.node_after(self)
245
- 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
- ###
254
- def list_next
255
- @parent or raise NoParent
256
- @parent.NodeList? or raise BadParent
257
- return @parent.node_after(self)
258
- 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
- ###
265
- def prev
266
- @parent or raise NoParent
267
- return @parent.node_before(self)
268
- 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
- ###
277
- def list_prev
278
- @parent or raise NoParent
279
- @parent.NodeList? or raise BadParent
280
- return @parent.node_before(self)
281
- end
282
- ###
283
- ### Detach this Node from the tree and return it.
284
- ###
285
- ### Raises NoParent if there's no parent.
286
- ###
287
- def detach
288
- @parent or raise NoParent
289
- @parent.remove_node(self)
290
- return self
291
- 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
302
- @parent or raise NoParent
303
- @parent.replace_node(self, *nodes)
304
- return self
305
- 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
- ###
311
- def swap_with node
312
- return self if node.equal? self
313
- if self.attached?
314
- if node.attached?
315
- ## both attached -- use placeholder
316
- placeholder = Default.new
317
- my_parent = @parent
318
- my_parent.replace_node(self, placeholder)
319
- node.parent.replace_node(node, self)
320
- my_parent.replace_node(placeholder, node)
321
- else
322
- ## only `self' attached
323
- @parent.replace_node(self, node)
324
- end
325
- else
326
- if node.attached?
327
- ## only `node' attached
328
- node.parent.replace_node(node, self)
329
- else
330
- ## neither attached -- nothing to do
331
- end
332
- end
333
- return self
334
- 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
343
- @parent or raise NoParent
344
- @parent.NodeList? or raise BadParent
345
- @parent.insert_before(self, *newnodes)
346
- return self
347
- 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
- @parent or raise NoParent
357
- @parent.NodeList? or raise BadParent
358
- @parent.insert_after(self, *newnodes)
359
- return self
360
- 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
- ###
367
- def detached?
368
- @parent.nil?
369
- 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
- ###
376
- def attached?
377
- !@parent.nil?
378
- end
379
-
380
- ###
381
- ### --------------------------------------------------------------
382
- ### Subclass management
383
- ### --------------------------------------------------------------
384
- ###
385
-
386
- ###
387
- ### The direct subclasses of this class (an Array of Class).
388
- ###
389
- attr_reader :subclasses
390
- ###
391
- ### Return all classes which have this class somewhere in its
392
- ### ancestry (an Array of Class).
393
- ###
394
- def self.subclasses_recursive
395
- ret = @subclasses.dup
396
- @subclasses.each{|c| ret.concat(c.subclasses_recursive)}
397
- return ret
398
- end
399
- ###
400
- ### Callback defined in Class.
401
- ###
402
- def self.inherited klass
403
- @subclasses << klass
404
- klass.instance_variable_set(:@subclasses, [])
405
- klass.instance_variable_set(:@fields , [])
406
- end
407
- ###
408
- ### Declare this class as abstract.
409
- ###
410
- def self.abstract
411
- end
412
-
413
- ## set the instance vars for Node
414
- @subclasses = []
415
- @fields = []
416
-
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
- ###
433
-
434
- private # -------------------------------------------------------
435
-
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
441
- fields = @fields
442
- newfield.index = fields.length
443
- fields << newfield
444
- ## getter
445
- define_method(newfield.reader) do
446
- instance_variable_get(newfield.var)
447
- end
448
- ## setter
449
- if newfield.child?
450
- define_method(newfield.writer) do |val|
451
- old = send(newfield.reader)
452
- return if val.equal? old
453
- ## detach the old Node
454
- old = self.send(newfield.reader)
455
- unless old.nil?
456
- old.instance_variable_set(:@parent, nil)
457
- end
458
- ## copy val if needed
459
- val = val.clone if !val.nil? && val.attached?
460
- ## set
461
- self.instance_variable_set(newfield.var, val)
462
- ## attach the new Node
463
- unless val.nil?
464
- val.instance_variable_set(:@parent, self)
465
- val.instance_variable_set(:@parent_field, newfield)
466
- end
467
- end
468
- else
469
- define_method(newfield.writer) do |val|
470
- instance_variable_set(newfield.var, val)
471
- end
472
- end
473
- end
474
- def self.fields
475
- @fields
476
- 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
513
- define_method(:initialize) do |*args|
514
- ## pop off the opts hash
515
- opts = args.last.is_a?(::Hash) ? args.pop : {}
516
-
517
- ## add positional args to opts
518
- args.each_with_index do |arg, i|
519
- opts[syms[i]] = arg
520
- end
521
-
522
- ## set field values
523
- fields.each do |field|
524
- key = field.init_key
525
- if opts.key?(key)
526
- send(field.writer, opts[key])
527
- else
528
- send(field.writer, field.make_default)
529
- end
530
- end
531
-
532
- ## pos, parent
533
- @pos = nil
534
- @parent = nil
535
- end
536
- end
537
-
538
- public # --------------------------------------------------------
539
-
540
- ###
541
- ### Declare a field with the given name and default value.
542
- ###
543
- def self.field name, default=:'no default'
544
- if default == :'no default'
545
- if name.to_s[-1] == ??
546
- default = false
547
- else
548
- default = nil
549
- end
550
- end
551
-
552
- ## if the field exists, just update its default, otherwise, add
553
- ## a new field
554
- self.fields.each do |field|
555
- if field.reader == name
556
- field.default = default
557
- return
558
- end
559
- end
560
- add_field Field.new(name, default)
561
- 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
- field = Field.new(name, default)
569
- field.child = true
570
- add_field field
571
- end
572
- ###
573
- ### Return the list of fields this object has. Don't modify the
574
- ### returned array!
575
- ###
576
- def fields
577
- self.class.fields
578
- end
579
-
580
- def method_missing meth, *args, &blk
581
- ## respond to `Module?'
582
- methstr = meth.to_s
583
- if methstr =~ /^([A-Z].*)\?$/ && C.const_defined?($1)
584
- klass = C.const_get($1)
585
- if klass.is_a?(::Module)
586
- return self.is_a?(klass)
587
- end
588
- end
589
-
590
- begin
591
- super
592
- rescue NoMethodError => e
593
- e.set_backtrace(caller)
594
- raise e
595
- end
596
- end
597
-
598
- ###
599
- ### ==============================================================
600
- ###
601
- ### Child management
602
- ###
603
- ### ==============================================================
604
- ###
605
-
606
- public # --------------------------------------------------------
607
-
608
- ###
609
- ### Return the Node that comes after the given Node in tree
610
- ### preorder.
611
- ###
612
- def node_after node
613
- node.parent.equal? self or
614
- raise ArgumentError, "node is not a child"
615
- fields = self.fields
616
- i = node.instance_variable_get(:@parent_field).index + 1
617
- (i...fields.length).each do |i|
618
- f = fields[i]
619
- if f.child? && (val = self.send(f.reader))
620
- return val
621
- end
622
- end
623
- return nil
624
- end
625
- ###
626
- ### Return the Node that comes before the given Node in tree
627
- ### preorder.
628
- ###
629
- def node_before node
630
- node.parent.equal? self or
631
- raise ArgumentError, "node is not a child"
632
- fields = self.fields
633
- i = node.instance_variable_get(:@parent_field).index - 1
634
- i.downto(0) do |i|
635
- f = fields[i]
636
- if f.child? && (val = self.send(f.reader))
637
- return val
638
- end
639
- end
640
- return nil
641
- end
642
- ###
643
- ### Remove the given Node.
644
- ###
645
- def remove_node node
646
- node.parent.equal? self or
647
- raise ArgumentError, "node is not a child"
648
- field = node.instance_variable_get(:@parent_field)
649
- node.instance_variable_set(:@parent, nil)
650
- node.instance_variable_set(:@parent_field, nil)
651
- self.instance_variable_set(field.var, nil)
652
- return self
653
- end
654
- ###
655
- ### Replace `node' with `newnode'.
656
- ###
657
- def replace_node node, newnode=nil
658
- node.parent.equal? self or
659
- raise ArgumentError, "node is not a child"
660
- field = node.instance_variable_get(:@parent_field)
661
- self.send(field.writer, newnode)
662
- return self
663
- end
664
-
665
- ###
666
- ### ==============================================================
667
- ###
668
- ### Node::Field
669
- ###
670
- ### ==============================================================
671
- ###
672
-
673
- private # -------------------------------------------------------
674
-
675
- class Field
676
- attr_accessor :var, :reader, :writer, :init_key, :index,
677
- :default
678
-
679
- ###
680
- ### True if this field is a child field, false otherwise.
681
- ###
682
- attr_writer :child
683
- def child?
684
- @child
685
- 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
- ###
691
- def make_default
692
- if @default.respond_to? :call
693
- @default.call
694
- else
695
- @default
696
- end
697
- end
698
-
699
- def initialize name, default
700
- name = name.to_s
701
-
702
- @child = false
703
- @reader = name.to_sym
704
- @default = default
705
-
706
- if name[-1] == ?? then name[-1] = '' end
707
- @init_key = name.to_sym
708
- @var = "@#{name}".to_sym
709
- @writer = "#{name}=".to_sym
710
- end
711
- end
712
-
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
- public # -------------------------------------------------------
725
-
726
- class Pos
727
- attr_accessor :filename, :line_num, :col_num
728
- def initialize filename, line_num, col_num
729
- @filename = filename
730
- @line_num = line_num
731
- @col_num = col_num
732
- end
733
- def to_s
734
- (@filename ? "#@filename:" : '') << "#@line_num:#@col_num"
735
- end
736
- def <=> x
737
- return nil if self.filename != x.filename
738
- return (self.line_num <=> x.line_num).nonzero? ||
739
- self.col_num <=> x.col_num
740
- end
741
- include Comparable
742
- end
743
- end
744
- end