cast 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ dir = File.dirname(File.expand_path(__FILE__))
2
+
3
+ require "#{dir}/node.rb"
4
+ require "#{dir}/node_list.rb"
5
+ require "#{dir}/c_nodes.rb"
6
+ require "#{dir}/c.tab.rb"
7
+ require "#{dir}/parse.rb"
8
+ require "#{dir}/to_s.rb"
9
+ require "#{dir}/to_debug.rb"
@@ -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