]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/ast.rb
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / offlineasm / ast.rb
CommitLineData
6fe7ccc8
A
1# Copyright (C) 2011 Apple Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22# THE POSSIBILITY OF SUCH DAMAGE.
23
93a37866
A
24require "config"
25
6fe7ccc8
A
26#
27# Base utility types for the AST.
28#
29
30# Valid methods for Node:
31#
32# node.children -> Returns an array of immediate children.
33#
34# node.descendents -> Returns an array of all strict descendants (children
35# and children of children, transitively).
36#
37# node.flatten -> Returns an array containing the strict descendants and
38# the node itself.
39#
40# node.filter(type) -> Returns an array containing those elements in
41# node.flatten that are of the given type (is_a? type returns true).
42#
43# node.mapChildren{|v| ...} -> Returns a new node with all children
44# replaced according to the given block.
45#
46# Examples:
47#
48# node.filter(Setting).uniq -> Returns all of the settings that the AST's
49# IfThenElse blocks depend on.
50#
51# node.filter(StructOffset).uniq -> Returns all of the structure offsets
52# that the AST depends on.
53
54class Node
55 attr_reader :codeOrigin
56
57 def initialize(codeOrigin)
58 @codeOrigin = codeOrigin
59 end
60
61 def codeOriginString
62 @codeOrigin.to_s
63 end
64
65 def descendants
66 children.collect{|v| v.flatten}.flatten
67 end
68
69 def flatten
70 [self] + descendants
71 end
72
73 def filter(type)
74 flatten.select{|v| v.is_a? type}
75 end
76end
77
78class NoChildren < Node
79 def initialize(codeOrigin)
80 super(codeOrigin)
81 end
82
83 def children
84 []
85 end
86
87 def mapChildren
88 self
89 end
90end
91
92class StructOffsetKey
93 attr_reader :struct, :field
94
95 def initialize(struct, field)
96 @struct = struct
97 @field = field
98 end
99
100 def hash
101 @struct.hash + @field.hash * 3
102 end
103
104 def eql?(other)
105 @struct == other.struct and @field == other.field
106 end
107end
108
109#
110# AST nodes.
111#
112
113class StructOffset < NoChildren
114 attr_reader :struct, :field
115
116 def initialize(codeOrigin, struct, field)
117 super(codeOrigin)
118 @struct = struct
119 @field = field
120 end
121
122 @@mapping = {}
123
124 def self.forField(codeOrigin, struct, field)
125 key = StructOffsetKey.new(struct, field)
126
127 unless @@mapping[key]
128 @@mapping[key] = StructOffset.new(codeOrigin, struct, field)
129 end
130 @@mapping[key]
131 end
132
133 def dump
134 "#{struct}::#{field}"
135 end
136
137 def <=>(other)
138 if @struct != other.struct
139 return @struct <=> other.struct
140 end
141 @field <=> other.field
142 end
143
144 def address?
145 false
146 end
147
148 def label?
149 false
150 end
151
152 def immediate?
153 true
154 end
155
156 def register?
157 false
158 end
159end
160
161class Sizeof < NoChildren
162 attr_reader :struct
163
164 def initialize(codeOrigin, struct)
165 super(codeOrigin)
166 @struct = struct
167 end
168
169 @@mapping = {}
170
171 def self.forName(codeOrigin, struct)
172 unless @@mapping[struct]
173 @@mapping[struct] = Sizeof.new(codeOrigin, struct)
174 end
175 @@mapping[struct]
176 end
177
178 def dump
179 "sizeof #{@struct}"
180 end
181
182 def <=>(other)
183 @struct <=> other.struct
184 end
185
186 def address?
187 false
188 end
189
190 def label?
191 false
192 end
193
194 def immediate?
195 true
196 end
197
198 def register?
199 false
200 end
201end
202
203class Immediate < NoChildren
204 attr_reader :value
205
206 def initialize(codeOrigin, value)
207 super(codeOrigin)
208 @value = value
209 raise "Bad immediate value #{value.inspect} at #{codeOriginString}" unless value.is_a? Integer
210 end
211
212 def dump
213 "#{value}"
214 end
215
216 def ==(other)
217 other.is_a? Immediate and other.value == @value
218 end
219
220 def address?
221 false
222 end
223
224 def label?
225 false
226 end
227
228 def immediate?
229 true
230 end
231
81345200
A
232 def immediateOperand?
233 true
234 end
235
6fe7ccc8
A
236 def register?
237 false
238 end
239end
240
241class AddImmediates < Node
242 attr_reader :left, :right
243
244 def initialize(codeOrigin, left, right)
245 super(codeOrigin)
246 @left = left
247 @right = right
248 end
249
250 def children
251 [@left, @right]
252 end
253
254 def mapChildren
255 AddImmediates.new(codeOrigin, (yield @left), (yield @right))
256 end
257
258 def dump
259 "(#{left.dump} + #{right.dump})"
260 end
261
81345200
A
262 def value
263 "#{left.value} + #{right.value}"
264 end
265
6fe7ccc8
A
266 def address?
267 false
268 end
269
270 def label?
271 false
272 end
273
274 def immediate?
275 true
276 end
277
81345200
A
278 def immediateOperand?
279 true
280 end
281
6fe7ccc8
A
282 def register?
283 false
284 end
285end
286
287class SubImmediates < Node
288 attr_reader :left, :right
289
290 def initialize(codeOrigin, left, right)
291 super(codeOrigin)
292 @left = left
293 @right = right
294 end
295
296 def children
297 [@left, @right]
298 end
299
300 def mapChildren
301 SubImmediates.new(codeOrigin, (yield @left), (yield @right))
302 end
303
304 def dump
305 "(#{left.dump} - #{right.dump})"
306 end
307
81345200
A
308 def value
309 "#{left.value} - #{right.value}"
310 end
311
6fe7ccc8
A
312 def address?
313 false
314 end
315
316 def label?
317 false
318 end
319
320 def immediate?
321 true
322 end
323
81345200
A
324 def immediateOperand?
325 true
326 end
327
6fe7ccc8
A
328 def register?
329 false
330 end
331end
332
333class MulImmediates < Node
334 attr_reader :left, :right
335
336 def initialize(codeOrigin, left, right)
337 super(codeOrigin)
338 @left = left
339 @right = right
340 end
341
342 def children
343 [@left, @right]
344 end
345
346 def mapChildren
347 MulImmediates.new(codeOrigin, (yield @left), (yield @right))
348 end
349
350 def dump
351 "(#{left.dump} * #{right.dump})"
352 end
353
354 def address?
355 false
356 end
357
358 def label?
359 false
360 end
361
362 def immediate?
363 true
364 end
365
81345200
A
366 def immediateOperand?
367 false
368 end
369
6fe7ccc8
A
370 def register?
371 false
372 end
373end
374
375class NegImmediate < Node
376 attr_reader :child
377
378 def initialize(codeOrigin, child)
379 super(codeOrigin)
380 @child = child
381 end
382
383 def children
384 [@child]
385 end
386
387 def mapChildren
388 NegImmediate.new(codeOrigin, (yield @child))
389 end
390
391 def dump
392 "(-#{@child.dump})"
393 end
394
395 def address?
396 false
397 end
398
399 def label?
400 false
401 end
402
403 def immediate?
404 true
405 end
406
81345200
A
407 def immediateOperand?
408 false
409 end
410
6fe7ccc8
A
411 def register?
412 false
413 end
414end
415
416class OrImmediates < Node
417 attr_reader :left, :right
418
419 def initialize(codeOrigin, left, right)
420 super(codeOrigin)
421 @left = left
422 @right = right
423 end
424
425 def children
426 [@left, @right]
427 end
428
429 def mapChildren
430 OrImmediates.new(codeOrigin, (yield @left), (yield @right))
431 end
432
433 def dump
434 "(#{left.dump} | #{right.dump})"
435 end
436
437 def address?
438 false
439 end
440
441 def label?
442 false
443 end
444
445 def immediate?
446 true
447 end
448
81345200
A
449 def immediateOperand?
450 false
451 end
452
6fe7ccc8
A
453 def register?
454 false
455 end
456end
457
458class AndImmediates < Node
459 attr_reader :left, :right
460
461 def initialize(codeOrigin, left, right)
462 super(codeOrigin)
463 @left = left
464 @right = right
465 end
466
467 def children
468 [@left, @right]
469 end
470
471 def mapChildren
472 AndImmediates.new(codeOrigin, (yield @left), (yield @right))
473 end
474
475 def dump
476 "(#{left.dump} & #{right.dump})"
477 end
478
479 def address?
480 false
481 end
482
483 def label?
484 false
485 end
486
487 def immediate?
488 true
489 end
490
81345200
A
491 def immediateOperand?
492 false
493 end
494
6fe7ccc8
A
495 def register?
496 false
497 end
498end
499
500class XorImmediates < Node
501 attr_reader :left, :right
502
503 def initialize(codeOrigin, left, right)
504 super(codeOrigin)
505 @left = left
506 @right = right
507 end
508
509 def children
510 [@left, @right]
511 end
512
513 def mapChildren
514 XorImmediates.new(codeOrigin, (yield @left), (yield @right))
515 end
516
517 def dump
518 "(#{left.dump} ^ #{right.dump})"
519 end
520
521 def address?
522 false
523 end
524
525 def label?
526 false
527 end
528
529 def immediate?
530 true
531 end
532
81345200
A
533 def immediateOperand?
534 false
535 end
536
6fe7ccc8
A
537 def register?
538 false
539 end
540end
541
542class BitnotImmediate < Node
543 attr_reader :child
544
545 def initialize(codeOrigin, child)
546 super(codeOrigin)
547 @child = child
548 end
549
550 def children
551 [@child]
552 end
553
554 def mapChildren
555 BitnotImmediate.new(codeOrigin, (yield @child))
556 end
557
558 def dump
559 "(~#{@child.dump})"
560 end
561
562 def address?
563 false
564 end
565
566 def label?
567 false
568 end
569
570 def immediate?
571 true
572 end
573
81345200
A
574 def immediateOperand?
575 false
576 end
577
6fe7ccc8
A
578 def register?
579 false
580 end
581end
582
ed1e77d3
A
583class StringLiteral < NoChildren
584 attr_reader :value
585
586 def initialize(codeOrigin, value)
587 super(codeOrigin)
588 @value = value[1..-2]
589 raise "Bad string literal #{value.inspect} at #{codeOriginString}" unless value.is_a? String
590 end
591
592 def dump
593 "#{value}"
594 end
595
596 def ==(other)
597 other.is_a? StringLiteral and other.value == @value
598 end
599
600 def address?
601 false
602 end
603
604 def label?
605 false
606 end
607
608 def immediate?
609 false
610 end
611
612 def immediateOperand?
613 false
614 end
615
616 def register?
617 false
618 end
619end
620
6fe7ccc8
A
621class RegisterID < NoChildren
622 attr_reader :name
623
624 def initialize(codeOrigin, name)
625 super(codeOrigin)
626 @name = name
627 end
628
629 @@mapping = {}
630
631 def self.forName(codeOrigin, name)
632 unless @@mapping[name]
633 @@mapping[name] = RegisterID.new(codeOrigin, name)
634 end
635 @@mapping[name]
636 end
637
638 def dump
639 name
640 end
641
642 def address?
643 false
644 end
645
646 def label?
647 false
648 end
649
650 def immediate?
651 false
652 end
653
654 def register?
655 true
656 end
657end
658
659class FPRegisterID < NoChildren
660 attr_reader :name
661
662 def initialize(codeOrigin, name)
663 super(codeOrigin)
664 @name = name
665 end
666
667 @@mapping = {}
668
669 def self.forName(codeOrigin, name)
670 unless @@mapping[name]
671 @@mapping[name] = FPRegisterID.new(codeOrigin, name)
672 end
673 @@mapping[name]
674 end
675
676 def dump
677 name
678 end
679
680 def address?
681 false
682 end
683
684 def label?
685 false
686 end
687
688 def immediate?
689 false
690 end
691
81345200
A
692 def immediateOperand?
693 false
694 end
695
6fe7ccc8
A
696 def register?
697 true
698 end
699end
700
701class SpecialRegister < NoChildren
702 def initialize(name)
703 @name = name
704 end
705
706 def address?
707 false
708 end
709
710 def label?
711 false
712 end
713
714 def immediate?
715 false
716 end
717
81345200
A
718 def immediateOperand?
719 false
720 end
721
6fe7ccc8
A
722 def register?
723 true
724 end
725end
726
727class Variable < NoChildren
728 attr_reader :name
729
730 def initialize(codeOrigin, name)
731 super(codeOrigin)
732 @name = name
733 end
734
735 @@mapping = {}
736
737 def self.forName(codeOrigin, name)
738 unless @@mapping[name]
739 @@mapping[name] = Variable.new(codeOrigin, name)
740 end
741 @@mapping[name]
742 end
743
744 def dump
745 name
746 end
747
748 def inspect
749 "<variable #{name} at #{codeOriginString}>"
750 end
751end
752
753class Address < Node
754 attr_reader :base, :offset
755
756 def initialize(codeOrigin, base, offset)
757 super(codeOrigin)
758 @base = base
759 @offset = offset
760 raise "Bad base for address #{base.inspect} at #{codeOriginString}" unless base.is_a? Variable or base.register?
761 raise "Bad offset for address #{offset.inspect} at #{codeOriginString}" unless offset.is_a? Variable or offset.immediate?
762 end
763
93a37866
A
764 def withOffset(extraOffset)
765 Address.new(codeOrigin, @base, Immediate.new(codeOrigin, @offset.value + extraOffset))
766 end
767
6fe7ccc8
A
768 def children
769 [@base, @offset]
770 end
771
772 def mapChildren
773 Address.new(codeOrigin, (yield @base), (yield @offset))
774 end
775
776 def dump
777 "#{offset.dump}[#{base.dump}]"
778 end
779
780 def address?
781 true
782 end
783
784 def label?
785 false
786 end
787
788 def immediate?
789 false
790 end
791
81345200
A
792 def immediateOperand?
793 true
794 end
795
6fe7ccc8
A
796 def register?
797 false
798 end
799end
800
801class BaseIndex < Node
802 attr_reader :base, :index, :scale, :offset
803
804 def initialize(codeOrigin, base, index, scale, offset)
805 super(codeOrigin)
806 @base = base
807 @index = index
808 @scale = scale
809 raise unless [1, 2, 4, 8].member? @scale
810 @offset = offset
811 end
812
813 def scaleShift
814 case scale
815 when 1
816 0
817 when 2
818 1
819 when 4
820 2
821 when 8
822 3
823 else
824 raise "Bad scale at #{codeOriginString}"
825 end
826 end
827
93a37866
A
828 def withOffset(extraOffset)
829 BaseIndex.new(codeOrigin, @base, @index, @scale, Immediate.new(codeOrigin, @offset.value + extraOffset))
830 end
831
6fe7ccc8
A
832 def children
833 [@base, @index, @offset]
834 end
835
836 def mapChildren
837 BaseIndex.new(codeOrigin, (yield @base), (yield @index), @scale, (yield @offset))
838 end
839
840 def dump
841 "#{offset.dump}[#{base.dump}, #{index.dump}, #{scale}]"
842 end
843
844 def address?
845 true
846 end
847
848 def label?
849 false
850 end
851
852 def immediate?
853 false
854 end
855
81345200
A
856 def immediateOperand?
857 false
858 end
859
6fe7ccc8
A
860 def register?
861 false
862 end
863end
864
865class AbsoluteAddress < NoChildren
866 attr_reader :address
867
868 def initialize(codeOrigin, address)
869 super(codeOrigin)
870 @address = address
871 end
872
93a37866
A
873 def withOffset(extraOffset)
874 AbsoluteAddress.new(codeOrigin, Immediate.new(codeOrigin, @address.value + extraOffset))
875 end
876
6fe7ccc8
A
877 def dump
878 "#{address.dump}[]"
879 end
880
881 def address?
882 true
883 end
884
885 def label?
886 false
887 end
888
889 def immediate?
890 false
891 end
892
81345200
A
893 def immediateOperand?
894 true
895 end
896
6fe7ccc8
A
897 def register?
898 false
899 end
900end
901
902class Instruction < Node
93a37866 903 attr_reader :opcode, :operands, :annotation
6fe7ccc8 904
93a37866 905 def initialize(codeOrigin, opcode, operands, annotation=nil)
6fe7ccc8
A
906 super(codeOrigin)
907 @opcode = opcode
908 @operands = operands
93a37866 909 @annotation = annotation
6fe7ccc8
A
910 end
911
912 def children
913 operands
914 end
915
916 def mapChildren(&proc)
93a37866 917 Instruction.new(codeOrigin, @opcode, @operands.map(&proc), @annotation)
6fe7ccc8
A
918 end
919
920 def dump
921 "\t" + opcode.to_s + " " + operands.collect{|v| v.dump}.join(", ")
922 end
93a37866
A
923
924 def lowerDefault
925 case opcode
926 when "localAnnotation"
927 $asm.putLocalAnnotation
928 when "globalAnnotation"
929 $asm.putGlobalAnnotation
ed1e77d3
A
930 when "emit"
931 $asm.puts "#{operands[0].dump}"
93a37866
A
932 else
933 raise "Unhandled opcode #{opcode} at #{codeOriginString}"
934 end
935 end
6fe7ccc8
A
936end
937
938class Error < NoChildren
939 def initialize(codeOrigin)
940 super(codeOrigin)
941 end
942
943 def dump
944 "\terror"
945 end
946end
947
948class ConstDecl < Node
949 attr_reader :variable, :value
950
951 def initialize(codeOrigin, variable, value)
952 super(codeOrigin)
953 @variable = variable
954 @value = value
955 end
956
957 def children
958 [@variable, @value]
959 end
960
961 def mapChildren
962 ConstDecl.new(codeOrigin, (yield @variable), (yield @value))
963 end
964
965 def dump
966 "const #{@variable.dump} = #{@value.dump}"
967 end
968end
969
970$labelMapping = {}
81345200 971$referencedExternLabels = Array.new
6fe7ccc8
A
972
973class Label < NoChildren
974 attr_reader :name
975
976 def initialize(codeOrigin, name)
977 super(codeOrigin)
978 @name = name
81345200
A
979 @extern = true
980 @global = false
6fe7ccc8
A
981 end
982
81345200 983 def self.forName(codeOrigin, name, definedInFile = false)
6fe7ccc8
A
984 if $labelMapping[name]
985 raise "Label name collision: #{name}" unless $labelMapping[name].is_a? Label
986 else
987 $labelMapping[name] = Label.new(codeOrigin, name)
988 end
81345200
A
989 if definedInFile
990 $labelMapping[name].clearExtern()
991 end
6fe7ccc8
A
992 $labelMapping[name]
993 end
81345200
A
994
995 def self.setAsGlobal(codeOrigin, name)
996 if $labelMapping[name]
997 label = $labelMapping[name]
998 raise "Label: #{name} declared global multiple times" unless not label.global?
999 label.setGlobal()
1000 else
1001 newLabel = Label.new(codeOrigin, name)
1002 newLabel.setGlobal()
1003 $labelMapping[name] = newLabel
1004 end
1005 end
1006
1007 def self.resetReferenced
1008 $referencedExternLabels = Array.new
1009 end
1010
1011 def self.forReferencedExtern()
1012 $referencedExternLabels.each {
1013 | label |
1014 yield "#{label.name}"
1015 }
1016 end
1017
1018 def clearExtern
1019 @extern = false
1020 end
1021
1022 def extern?
1023 @extern
1024 end
1025
1026 def setGlobal
1027 @global = true
1028 end
1029
1030 def global?
1031 @global
1032 end
1033
6fe7ccc8
A
1034 def dump
1035 "#{name}:"
1036 end
1037end
1038
1039class LocalLabel < NoChildren
1040 attr_reader :name
1041
1042 def initialize(codeOrigin, name)
1043 super(codeOrigin)
1044 @name = name
1045 end
1046
1047 @@uniqueNameCounter = 0
1048
1049 def self.forName(codeOrigin, name)
1050 if $labelMapping[name]
1051 raise "Label name collision: #{name}" unless $labelMapping[name].is_a? LocalLabel
1052 else
1053 $labelMapping[name] = LocalLabel.new(codeOrigin, name)
1054 end
1055 $labelMapping[name]
1056 end
1057
1058 def self.unique(comment)
1059 newName = "_#{comment}"
1060 if $labelMapping[newName]
1061 while $labelMapping[newName = "_#{@@uniqueNameCounter}_#{comment}"]
1062 @@uniqueNameCounter += 1
1063 end
1064 end
1065 forName(nil, newName)
1066 end
1067
1068 def cleanName
1069 if name =~ /^\./
1070 "_" + name[1..-1]
1071 else
1072 name
1073 end
1074 end
1075
1076 def dump
1077 "#{name}:"
1078 end
1079end
1080
1081class LabelReference < Node
1082 attr_reader :label
1083
1084 def initialize(codeOrigin, label)
1085 super(codeOrigin)
1086 @label = label
1087 end
1088
1089 def children
1090 [@label]
1091 end
1092
1093 def mapChildren
1094 LabelReference.new(codeOrigin, (yield @label))
1095 end
1096
1097 def name
1098 label.name
1099 end
1100
81345200
A
1101 def extern?
1102 $labelMapping[name].is_a? Label and $labelMapping[name].extern?
1103 end
1104
1105 def used
1106 if !$referencedExternLabels.include?(@label) and extern?
1107 $referencedExternLabels.push(@label)
1108 end
1109 end
1110
6fe7ccc8
A
1111 def dump
1112 label.name
1113 end
1114
81345200
A
1115 def value
1116 asmLabel()
1117 end
1118
6fe7ccc8
A
1119 def address?
1120 false
1121 end
1122
1123 def label?
1124 true
1125 end
1126
1127 def immediate?
1128 false
1129 end
81345200
A
1130
1131 def immediateOperand?
1132 true
1133 end
6fe7ccc8
A
1134end
1135
1136class LocalLabelReference < NoChildren
1137 attr_reader :label
1138
1139 def initialize(codeOrigin, label)
1140 super(codeOrigin)
1141 @label = label
1142 end
1143
1144 def children
1145 [@label]
1146 end
1147
1148 def mapChildren
1149 LocalLabelReference.new(codeOrigin, (yield @label))
1150 end
1151
1152 def name
1153 label.name
1154 end
1155
1156 def dump
1157 label.name
1158 end
81345200
A
1159
1160 def value
1161 asmLabel()
1162 end
6fe7ccc8
A
1163
1164 def address?
1165 false
1166 end
1167
1168 def label?
1169 true
1170 end
1171
1172 def immediate?
1173 false
1174 end
81345200
A
1175
1176 def immediateOperand?
1177 true
1178 end
6fe7ccc8
A
1179end
1180
1181class Sequence < Node
1182 attr_reader :list
1183
1184 def initialize(codeOrigin, list)
1185 super(codeOrigin)
1186 @list = list
1187 end
1188
1189 def children
1190 list
1191 end
1192
1193 def mapChildren(&proc)
1194 Sequence.new(codeOrigin, @list.map(&proc))
1195 end
1196
1197 def dump
1198 list.collect{|v| v.dump}.join("\n")
1199 end
1200end
1201
1202class True < NoChildren
1203 def initialize
1204 super(nil)
1205 end
1206
1207 @@instance = True.new
1208
1209 def self.instance
1210 @@instance
1211 end
1212
1213 def value
1214 true
1215 end
1216
1217 def dump
1218 "true"
1219 end
1220end
1221
1222class False < NoChildren
1223 def initialize
1224 super(nil)
1225 end
1226
1227 @@instance = False.new
1228
1229 def self.instance
1230 @@instance
1231 end
1232
1233 def value
1234 false
1235 end
1236
1237 def dump
1238 "false"
1239 end
1240end
1241
1242class TrueClass
1243 def asNode
1244 True.instance
1245 end
1246end
1247
1248class FalseClass
1249 def asNode
1250 False.instance
1251 end
1252end
1253
1254class Setting < NoChildren
1255 attr_reader :name
1256
1257 def initialize(codeOrigin, name)
1258 super(codeOrigin)
1259 @name = name
1260 end
1261
1262 @@mapping = {}
1263
1264 def self.forName(codeOrigin, name)
1265 unless @@mapping[name]
1266 @@mapping[name] = Setting.new(codeOrigin, name)
1267 end
1268 @@mapping[name]
1269 end
1270
1271 def dump
1272 name
1273 end
1274end
1275
1276class And < Node
1277 attr_reader :left, :right
1278
1279 def initialize(codeOrigin, left, right)
1280 super(codeOrigin)
1281 @left = left
1282 @right = right
1283 end
1284
1285 def children
1286 [@left, @right]
1287 end
1288
1289 def mapChildren
1290 And.new(codeOrigin, (yield @left), (yield @right))
1291 end
1292
1293 def dump
1294 "(#{left.dump} and #{right.dump})"
1295 end
1296end
1297
1298class Or < Node
1299 attr_reader :left, :right
1300
1301 def initialize(codeOrigin, left, right)
1302 super(codeOrigin)
1303 @left = left
1304 @right = right
1305 end
1306
1307 def children
1308 [@left, @right]
1309 end
1310
1311 def mapChildren
1312 Or.new(codeOrigin, (yield @left), (yield @right))
1313 end
1314
1315 def dump
1316 "(#{left.dump} or #{right.dump})"
1317 end
1318end
1319
1320class Not < Node
1321 attr_reader :child
1322
1323 def initialize(codeOrigin, child)
1324 super(codeOrigin)
1325 @child = child
1326 end
1327
1328 def children
93a37866 1329 [@child]
6fe7ccc8
A
1330 end
1331
1332 def mapChildren
1333 Not.new(codeOrigin, (yield @child))
1334 end
1335
1336 def dump
1337 "(not #{child.dump})"
1338 end
1339end
1340
1341class Skip < NoChildren
1342 def initialize(codeOrigin)
1343 super(codeOrigin)
1344 end
1345
1346 def dump
1347 "\tskip"
1348 end
1349end
1350
1351class IfThenElse < Node
1352 attr_reader :predicate, :thenCase
1353 attr_accessor :elseCase
1354
1355 def initialize(codeOrigin, predicate, thenCase)
1356 super(codeOrigin)
1357 @predicate = predicate
1358 @thenCase = thenCase
1359 @elseCase = Skip.new(codeOrigin)
1360 end
1361
1362 def children
1363 if @elseCase
1364 [@predicate, @thenCase, @elseCase]
1365 else
1366 [@predicate, @thenCase]
1367 end
1368 end
1369
1370 def mapChildren
1371 IfThenElse.new(codeOrigin, (yield @predicate), (yield @thenCase), (yield @elseCase))
1372 end
1373
1374 def dump
1375 "if #{predicate.dump}\n" + thenCase.dump + "\nelse\n" + elseCase.dump + "\nend"
1376 end
1377end
1378
1379class Macro < Node
1380 attr_reader :name, :variables, :body
93a37866 1381
6fe7ccc8
A
1382 def initialize(codeOrigin, name, variables, body)
1383 super(codeOrigin)
1384 @name = name
1385 @variables = variables
1386 @body = body
1387 end
1388
1389 def children
1390 @variables + [@body]
1391 end
1392
1393 def mapChildren
1394 Macro.new(codeOrigin, @name, @variables.map{|v| yield v}, (yield @body))
1395 end
1396
1397 def dump
1398 "macro #{name}(" + variables.collect{|v| v.dump}.join(", ") + ")\n" + body.dump + "\nend"
1399 end
1400end
1401
1402class MacroCall < Node
93a37866 1403 attr_reader :name, :operands, :annotation
6fe7ccc8 1404
93a37866 1405 def initialize(codeOrigin, name, operands, annotation)
6fe7ccc8
A
1406 super(codeOrigin)
1407 @name = name
1408 @operands = operands
1409 raise unless @operands
1410 @operands.each{|v| raise unless v}
93a37866 1411 @annotation = annotation
6fe7ccc8
A
1412 end
1413
1414 def children
1415 @operands
1416 end
1417
1418 def mapChildren(&proc)
93a37866 1419 MacroCall.new(codeOrigin, @name, @operands.map(&proc), @annotation)
6fe7ccc8
A
1420 end
1421
1422 def dump
1423 "\t#{name}(" + operands.collect{|v| v.dump}.join(", ") + ")"
1424 end
1425end
1426