cast19 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ ###
2
+ ### ##################################################################
3
+ ###
4
+ ### Node#inspect.
5
+ ###
6
+ ### ##################################################################
7
+ ###
8
+
9
+ module C
10
+ class Node
11
+ INSPECT_TAB = ' '
12
+ def inspect
13
+ return Node.inspect1(self)
14
+ end
15
+
16
+ def Node.inspect1 x, prefix='', indent=0, is_child=true
17
+ case x
18
+ when NodeList
19
+ if x.empty?
20
+ return "#{INSPECT_TAB*indent}#{prefix}[]\n"
21
+ else
22
+ str = "#{INSPECT_TAB*indent}#{prefix}\n"
23
+ x.each do |el|
24
+ str << inspect1(el, "- ", indent+1)
25
+ end
26
+ return str
27
+ end
28
+ when Node
29
+ classname = x.class.name.gsub(/^C::/, '')
30
+ str = "#{INSPECT_TAB*indent}#{prefix}#{classname}"
31
+
32
+ fields = x.fields
33
+ bools, others = fields.partition{|field| field.reader.to_s[-1] == ??}
34
+ bools.delete_if{|field| !x.send(field.reader)}
35
+ bools.map!{|field| field.init_key}
36
+
37
+ unless bools == []
38
+ str << " (#{bools.join(' ')})"
39
+ end
40
+ str << "\n"
41
+
42
+ others.each do |field|
43
+ val = x.send(field.reader)
44
+ next if val == field.make_default ||
45
+ ## don't bother with non-child Nodes, since they may cause
46
+ ## loops in the tree
47
+ (val.is_a?(Node) && !field.child?)
48
+ str << inspect1(val, "#{field.reader}: ", indent+1, field.child?)
49
+ end
50
+ return str
51
+ when Symbol
52
+ return "#{INSPECT_TAB*indent}#{prefix}#{x}\n"
53
+ else
54
+ return "#{INSPECT_TAB*indent}#{prefix}#{x.inspect}\n"
55
+ end
56
+ return s.string
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,744 @@
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