cast 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,233 @@
1
+ ###
2
+ ### ##################################################################
3
+ ###
4
+ ### C.default_parser and the parse_* methods.
5
+ ###
6
+ ### Yeah, this could be so much faster.
7
+ ###
8
+ ### ##################################################################
9
+ ###
10
+
11
+ module C
12
+ @@default_parser = Parser.new
13
+ def self.default_parser
14
+ @@default_parser
15
+ end
16
+ def self.default_parser= val
17
+ @@default_parser = val
18
+ end
19
+
20
+ class Node
21
+ ###
22
+ ### Return true if `str' is parsed to something `==' to this Node.
23
+ ### str is first converted to a String using #to_s, then given to
24
+ ### self.class.parse (along with the optional `parser').
25
+ ###
26
+ def match? str, parser=nil
27
+ node = self.class.parse(str.to_s, parser) rescue (return false)
28
+ self == node
29
+ end
30
+ ###
31
+ ### Same as #match?.
32
+ ###
33
+ def =~ *args
34
+ match? *args
35
+ end
36
+ private
37
+ end
38
+ class NodeList
39
+ ###
40
+ ### As defined in Node.
41
+ ###
42
+ def match? arr, parser=nil
43
+ arr = arr.to_a
44
+ return false if arr.length != self.length
45
+ each_with_index do |node, i|
46
+ node.match?(arr[i], parser) or return false
47
+ end
48
+ return true
49
+ end
50
+ end
51
+
52
+ def self.parse s, parser=nil
53
+ TranslationUnit.parse(s, parser)
54
+ end
55
+
56
+ class TranslationUnit
57
+ def self.parse s, parser=nil
58
+ parser ||= C.default_parser
59
+ parser.parse(s)
60
+ end
61
+ end
62
+
63
+ class Declaration
64
+ def self.parse s, parser=nil
65
+ parser ||= C.default_parser
66
+ ents = parser.parse(s).entities
67
+ if ents.length == 1 && # int i; int j;
68
+ ents[0].is_a?(Declaration) # void f() {}
69
+ return ents[0].detach
70
+ else
71
+ raise ParseError, "invalid Declaration"
72
+ end
73
+ end
74
+ end
75
+
76
+ class Parameter
77
+ def self.parse s, parser=nil
78
+ parser ||= C.default_parser
79
+ ents = parser.parse("void f(#{s}) {}").entities
80
+ if ents.length == 1 && # ) {} void (
81
+ ents[0].is_a?(FunctionDef) && # ); void(
82
+ ents[0].type.params && #
83
+ ents[0].type.params.length <= 1 # x,y
84
+ param = ents[0].type.params[0]
85
+ if param.nil?
86
+ return Parameter.new(Void.new)
87
+ else
88
+ return param.detach
89
+ end
90
+ else
91
+ raise ParseError, "invalid Parameter"
92
+ end
93
+ end
94
+ end
95
+
96
+ class Declarator
97
+ def self.parse s, parser=nil
98
+ parser ||= C.default_parser
99
+ ents = parser.parse("int #{s};").entities
100
+ if ents.length == 1 && # f; int f;
101
+ ents[0].declarators.length == 1 # i,j
102
+ return ents[0].declarators[0].detach
103
+ else
104
+ raise ParseError, "invalid Declarator"
105
+ end
106
+ end
107
+ end
108
+
109
+ class FunctionDef
110
+ def self.parse s, parser=nil
111
+ parser ||= C.default_parser
112
+ ents = parser.parse(s).entities
113
+ if ents.length == 1 && # void f(); void g();
114
+ ents[0].is_a?(FunctionDef) # int i;
115
+ return ents[0].detach
116
+ else
117
+ raise ParseError, "invalid FunctionDef"
118
+ end
119
+ end
120
+ end
121
+
122
+ class Enumerator
123
+ def self.parse s, parser=nil
124
+ parser ||= C.default_parser
125
+ ents = parser.parse("enum {#{s}};").entities
126
+ if ents.length == 1 && # } enum {
127
+ ents[0].is_a?(Declaration) && # } f() {
128
+ ents[0].type.members.length == 1 # X, Y
129
+ return ents[0].type.members[0].detach
130
+ else
131
+ raise ParseError, "invalid Enumerator"
132
+ end
133
+ end
134
+ end
135
+
136
+ class MemberInit
137
+ def self.parse s, parser=nil
138
+ parser ||= C.default_parser
139
+ ents = parser.parse("int f() {struct s x = {#{s}};}").entities
140
+ if ents.length == 1 && # } int f() {
141
+ ents[0].def.stmts.length == 1 && # }} f() {{
142
+ ents[0].def.stmts[0].declarators.length == 1 && # 1}, y
143
+ ents[0].def.stmts[0].declarators[0].init.member_inits.length == 1 # 1, 2
144
+ return ents[0].def.stmts[0].declarators[0].init.member_inits[0].detach
145
+ else
146
+ raise ParseError, "invalid MemberInit"
147
+ end
148
+ end
149
+ end
150
+
151
+ class Member
152
+ def self.parse s, parser=nil
153
+ parser ||= C.default_parser
154
+ ents = parser.parse("int f() {struct s x = {#{s} = 1;};}").entities
155
+ if ents.length == 1 && # };} int f() {struct s x = {a
156
+ ents[0].def.stmts.length == 1 && # }; x
157
+ #ents[0].def.stmts[0].length == 1 && # 1}, x = {.a
158
+ ents[0].def.stmts[0].declarators.length == 1 && # 1}, x = {.a
159
+ ents[0].def.stmts[0].declarators[0].init.member_inits.length == 1 && # x = 1, y
160
+ ents[0].def.stmts[0].declarators[0].init.member_inits[0].member.length == 1 && # .a .b
161
+ ents[0].def.stmts[0].declarators[0].init.member_inits[0].member[0].is_a?(C::Member) # [0]
162
+ return ents[0].def.stmts[0].declarators[0].init.member_inits[0].member[0].detach
163
+ else
164
+ raise ParseError, "invalid Member"
165
+ end
166
+ end
167
+ end
168
+
169
+ class Statement
170
+ def self.parse s, parser=nil
171
+ parser ||= C.default_parser
172
+ ents = parser.parse("void f() {#{s}}").entities
173
+ if ents.length == 1 && # } void f() {
174
+ ents[0].def.stmts.length == 1 && # ;;
175
+ ents[0].def.stmts[0].is_a?(self) # int i;
176
+ return ents[0].def.stmts[0].detach
177
+ else
178
+ raise ParseError, "invalid #{self}"
179
+ end
180
+ end
181
+ end
182
+
183
+ class Label
184
+ def self.parse s, parser=nil
185
+ parser ||= C.default_parser
186
+ ents = parser.parse("void f() {switch (0) #{s};}").entities
187
+ if ents.length == 1 && # } void f() {
188
+ ents[0].def.stmts.length == 1 && # ;
189
+ ents[0].def.stmts[0].stmt && #
190
+ ents[0].def.stmts[0].stmt.labels.length == 1 && # x
191
+ ents[0].def.stmts[0].stmt.labels[0].is_a?(self)
192
+ return ents[0].def.stmts[0].stmt.labels[0].detach
193
+ else
194
+ raise ParseError, "invalid #{self}"
195
+ end
196
+ end
197
+ end
198
+
199
+ class Expression
200
+ def self.parse s, parser=nil
201
+ parser ||= C.default_parser
202
+ ents = parser.parse("void f() {#{s};}").entities
203
+ if ents.length == 1 && # } void f() {
204
+ ents[0].def.stmts.length == 1 && # ;
205
+ ents[0].def.stmts[0].is_a?(ExpressionStatement) && # int i
206
+ ents[0].def.stmts[0].expr.is_a?(self)
207
+ return ents[0].def.stmts[0].expr.detach
208
+ else
209
+ raise ParseError, "invalid #{self}"
210
+ end
211
+ end
212
+ end
213
+
214
+ class Type
215
+ def self.parse s, parser=nil
216
+ parser ||= C.default_parser
217
+ ents = parser.parse("void f() {(#{s})x;}").entities
218
+ if ents.length == 1 && # 1);} void f() {(int
219
+ ents[0].def.stmts.length == 1 && # 1); (int
220
+ ents[0].def.stmts[0].expr.type.is_a?(self)
221
+ return ents[0].def.stmts[0].expr.type.detach
222
+ else
223
+ raise ParseError, "invalid #{self}"
224
+ end
225
+ end
226
+ end
227
+
228
+ #### Make sure we didn't miss any
229
+ CORE_C_NODE_CLASSES.each do |c|
230
+ c.methods.include? 'parse' or
231
+ raise "#{c}#parse not defined"
232
+ end
233
+ end
@@ -0,0 +1,59 @@
1
+ ###
2
+ ### ##################################################################
3
+ ###
4
+ ### Node#to_debug.
5
+ ###
6
+ ### ##################################################################
7
+ ###
8
+
9
+ module C
10
+ class Node
11
+ TO_DEBUG_TAB = ' '
12
+ def to_debug
13
+ return Node.to_debug1(self)
14
+ end
15
+
16
+ def Node.to_debug1 x, prefix='', indent=0, is_child=true
17
+ case x
18
+ when NodeList
19
+ if x.empty?
20
+ return "#{TO_DEBUG_TAB*indent}#{prefix}[]\n"
21
+ else
22
+ str = "#{TO_DEBUG_TAB*indent}#{prefix}\n"
23
+ x.each do |el|
24
+ str << to_debug1(el, "- ", indent+1)
25
+ end
26
+ return str
27
+ end
28
+ when Node
29
+ classname = x.class.name.gsub(/^C::/, '')
30
+ str = "#{TO_DEBUG_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 << to_debug1(val, "#{field.reader}: ", indent+1, field.child?)
49
+ end
50
+ return str
51
+ when Symbol
52
+ return "#{TO_DEBUG_TAB*indent}#{prefix}#{x}\n"
53
+ else
54
+ return "#{TO_DEBUG_TAB*indent}#{prefix}#{x.inspect}\n"
55
+ end
56
+ return s.string
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,538 @@
1
+ ###
2
+ ### ##################################################################
3
+ ###
4
+ ### The Node#to_s methods.
5
+ ###
6
+ ### Yeah, this could be so so *SO* much faster.
7
+ ###
8
+ ### ##################################################################
9
+ ###
10
+
11
+ module C
12
+ ## undef the #to_s methods so we can check that we didn't forget to
13
+ ## define any
14
+ Node.send(:undef_method, :to_s)
15
+
16
+ INDENT = ' '
17
+ class Node
18
+ private
19
+ def indent s, levels=1
20
+ s.gsub(/^/, INDENT*levels)
21
+ end
22
+ def hang stmt, cont=false
23
+ if stmt.is_a? Block
24
+ return " #{stmt.to_s(:hanging)}" << (cont ? ' ' : '')
25
+ else
26
+ return "\n#{stmt.to_s}" << (cont ? "\n" : '')
27
+ end
28
+ end
29
+ end
30
+
31
+ class TranslationUnit
32
+ def to_s
33
+ entities.map{|n| n.to_s}.join("\n\n")
34
+ end
35
+ end
36
+ class Declaration
37
+ def to_s
38
+ str = ''
39
+ inline? and str << "inline "
40
+ storage and str << "#{storage} "
41
+ if declarators.empty?
42
+ return str << "#{type};"
43
+ else
44
+ return str << "#{type} " << declarators.join(', ') << ';'
45
+ end
46
+ end
47
+ end
48
+ class Declarator
49
+ def to_s
50
+ (indirect_type ? indirect_type.to_s(name) : name.dup) <<
51
+ (init ? " = #{init}" : '') <<
52
+ (num_bits ? " : #{num_bits}" : '')
53
+ end
54
+ end
55
+ class FunctionDef
56
+ def to_s
57
+ str = ''
58
+ static? and str << 'static '
59
+ inline? and str << 'inline '
60
+ if no_prototype?
61
+ str << "#{type.to_s(name)}\n"
62
+ type.params.each do |p|
63
+ str << indent("#{p.to_s};\n")
64
+ end
65
+ str << "#{self.def.to_s(:hanging)}"
66
+ else
67
+ str << "#{type.to_s(name)}#{hang(self.def)}"
68
+ end
69
+ end
70
+ end
71
+
72
+ ### Statements
73
+ class Statement
74
+ def label str
75
+ labels.map{|s| "#{s}:\n"}.join + indent(str)
76
+ end
77
+ end
78
+ class Block
79
+ def to_s hanging=false
80
+ str = stmts.map do |s|
81
+ if s.is_a? Statement
82
+ s.to_s
83
+ else
84
+ indent(s.to_s)
85
+ end
86
+ end.join("\n")
87
+ str << "\n" unless str == ''
88
+ str = "{\n" << str << "}"
89
+ if hanging
90
+ if labels.empty?
91
+ return str
92
+ else
93
+ return "\n" << label(str)
94
+ end
95
+ else
96
+ return label(str)
97
+ end
98
+ end
99
+ end
100
+ class If
101
+ def to_s
102
+ str = "if (#{cond})"
103
+ if self.else.nil?
104
+ str << hang(self.then)
105
+ else
106
+ str << hang(self.then, :cont) << 'else' << hang(self.else)
107
+ end
108
+ return label(str)
109
+ end
110
+ end
111
+ class Switch
112
+ def to_s
113
+ label("switch (#{cond})" << hang(stmt))
114
+ end
115
+ end
116
+ class While
117
+ def to_s
118
+ if do?
119
+ label('do' << hang(stmt, :cont) << "while (#{cond});")
120
+ else
121
+ label("while (#{cond})" << hang(stmt))
122
+ end
123
+ end
124
+ end
125
+ class For
126
+ def to_s
127
+ initstr =
128
+ case init
129
+ when nil
130
+ ';'
131
+ when Declaration
132
+ "#{init}"
133
+ else
134
+ "#{init};"
135
+ end
136
+ condstr = cond ? " #{cond};" : ';'
137
+ iterstr = iter ? " #{iter}" : ''
138
+ label("for (#{initstr}#{condstr}#{iterstr})" << hang(stmt))
139
+ end
140
+ end
141
+ class Goto
142
+ def to_s
143
+ label("goto #{target};")
144
+ end
145
+ end
146
+ class Continue
147
+ def to_s
148
+ label("continue;")
149
+ end
150
+ end
151
+ class Break
152
+ def to_s
153
+ label("break;")
154
+ end
155
+ end
156
+ class Return
157
+ def to_s
158
+ label("return#{expr ? ' '+expr.to_s : ''};")
159
+ end
160
+ end
161
+ class ExpressionStatement
162
+ def to_s
163
+ label("#{expr};")
164
+ end
165
+ end
166
+
167
+ class PlainLabel
168
+ def to_s
169
+ name.to_s
170
+ end
171
+ end
172
+ class Default
173
+ def to_s
174
+ 'default'
175
+ end
176
+ end
177
+ class Case
178
+ def to_s
179
+ "case #{expr}"
180
+ end
181
+ end
182
+
183
+ ### Expressions
184
+ precedence_table = {}
185
+ [[Comma],
186
+ [Assign, MultiplyAssign, DivideAssign, ModAssign, AddAssign,
187
+ SubtractAssign, ShiftLeftAssign, ShiftRightAssign, BitAndAssign,
188
+ BitXorAssign, BitOrAssign],
189
+ [Conditional],
190
+ [Or],
191
+ [And],
192
+ [BitOr],
193
+ [BitXor],
194
+ [BitAnd],
195
+ [Equal, NotEqual],
196
+ [Less, More, LessOrEqual, MoreOrEqual],
197
+ [ShiftLeft, ShiftRight],
198
+ [Add, Subtract],
199
+ [Multiply, Divide, Mod],
200
+ [PreInc, PreDec, Sizeof, Cast, Address, Dereference, Positive, Negative,
201
+ BitNot, Not],
202
+ [Index, Call, Arrow, Dot, PostInc, PostDec],
203
+ [Literal, Variable]
204
+ ].each_with_index do |klasses, prec|
205
+ klasses.each do |klass|
206
+ klass.send(:define_method, :to_s_precedence){|| prec}
207
+ end
208
+ end
209
+ ## check all Expression classes have a precedence
210
+ C::Expression.subclasses_recursive do |c|
211
+ next if !C::Node.subclasses_recursive.include? c
212
+ c.instance_methods.include? 'to_s_precedence' or
213
+ raise "#{c}#to_s_precedence not defined"
214
+ end
215
+
216
+ ## PrefixExpressions
217
+ [ [Cast , lambda{"(#{self.type})"}],
218
+ [Address , lambda{"&" }],
219
+ [Dereference, lambda{"*" }],
220
+ [Positive , lambda{"+" }],
221
+ [Negative , lambda{"-" }],
222
+ [PreInc , lambda{"++" }],
223
+ [PreDec , lambda{"--" }],
224
+ [BitNot , lambda{"~" }],
225
+ [Not , lambda{"!" }]
226
+ ].each do |c, proc|
227
+ c.send(:define_method, :to_s) do | |
228
+ if expr.to_s_precedence < self.to_s_precedence
229
+ return "#{instance_eval(&proc)}(#{expr})"
230
+ else
231
+ return "#{instance_eval(&proc)}#{expr}"
232
+ end
233
+ end
234
+ end
235
+ ## PostfixExpressions
236
+ [ [Arrow , lambda{"->#{member}"}],
237
+ [Dot , lambda{".#{member}" }],
238
+ [Index , lambda{"[#{index}]" }],
239
+ [PostInc , lambda{"++" }],
240
+ [PostDec , lambda{"--" }]
241
+ ].each do |c, proc|
242
+ c.send(:define_method, :to_s) do | |
243
+ if expr.to_s_precedence < self.to_s_precedence
244
+ return "(#{expr})#{instance_eval(&proc)}"
245
+ else
246
+ return "#{expr}#{instance_eval(&proc)}"
247
+ end
248
+ end
249
+ end
250
+ ## BinaryExpressions
251
+ [ [Add , '+' ],
252
+ [Subtract , '-' ],
253
+ [Multiply , '*' ],
254
+ [Divide , '/' ],
255
+ [Mod , '%' ],
256
+ [Equal , '=='],
257
+ [NotEqual , '!='],
258
+ [Less , '<' ],
259
+ [More , '>' ],
260
+ [LessOrEqual, '<='],
261
+ [MoreOrEqual, '>='],
262
+ [BitAnd , '&' ],
263
+ [BitOr , '|' ],
264
+ [BitXor , '^' ],
265
+ [ShiftLeft , '<<'],
266
+ [ShiftRight , '>>'],
267
+ [And , '&&'],
268
+ [Or , '||'],
269
+ ].each do |c, op|
270
+ c.send(:define_method, :to_s) do | |
271
+ if expr1.to_s_precedence < self.to_s_precedence
272
+ str1 = "(#{expr1})"
273
+ else
274
+ str1 = "#{expr1}"
275
+ end
276
+ ## all binary expressions are left associative
277
+ if expr2.to_s_precedence <= self.to_s_precedence
278
+ str2 = "(#{expr2})"
279
+ else
280
+ str2 = "#{expr2}"
281
+ end
282
+ "#{str1} #{op} #{str2}"
283
+ end
284
+ end
285
+ ## AssignmentExpressions
286
+ [ [Assign , '' ],
287
+ [MultiplyAssign , '*' ],
288
+ [DivideAssign , '/' ],
289
+ [ModAssign , '%' ],
290
+ [AddAssign , '+' ],
291
+ [SubtractAssign , '-' ],
292
+ [ShiftLeftAssign , '<<'],
293
+ [ShiftRightAssign, '>>'],
294
+ [BitAndAssign , '&' ],
295
+ [BitXorAssign , '^' ],
296
+ [BitOrAssign , '|' ]
297
+ ].each do |c, op|
298
+ c.send(:define_method, :to_s) do | |
299
+ if rval.to_s_precedence < self.to_s_precedence
300
+ rvalstr = "(#{rval})"
301
+ else
302
+ rvalstr = "#{rval}"
303
+ end
304
+ "#{lval} #{op}= #{rvalstr}"
305
+ end
306
+ end
307
+ ## Other Expressions
308
+ class Sizeof
309
+ def to_s
310
+ if expr.is_a? Expression
311
+ if expr.to_s_precedence < self.to_s_precedence
312
+ return "sizeof(#{expr})"
313
+ else
314
+ return "sizeof #{expr}"
315
+ end
316
+ else
317
+ return "sizeof(#{expr})"
318
+ end
319
+ end
320
+ end
321
+ ## DirectTypes
322
+ int_longnesses = ['short ', '', 'long ', 'long long ']
323
+ float_longnesses = ['float', 'double', 'long double']
324
+ [ [Struct, lambda do
325
+ str = 'struct'
326
+ name and str << " #{name}"
327
+ members and str << " {\n" << indent(members.join("\n")) << "\n}"
328
+ str
329
+ end],
330
+ [Union, lambda do
331
+ str = 'union'
332
+ name and str << " #{name}"
333
+ members and str << " {\n" << indent(members.join("\n")) << "\n}"
334
+ str
335
+ end],
336
+ [Enum, lambda do
337
+ str = 'enum'
338
+ name and str << " #{name}"
339
+ members and str << " {\n" << indent(members.join(",\n")) << "\n}"
340
+ str
341
+ end],
342
+ [CustomType, lambda{name.dup }],
343
+ [Void , lambda{'void' }],
344
+ [Int , lambda do
345
+ longness_str = int_longnesses[longness+1].dup
346
+ "#{unsigned? ? 'unsigned ' : ''}#{longness_str}int"
347
+ end],
348
+ [Float , lambda{float_longnesses[longness].dup}],
349
+ [Char , lambda{"#{unsigned? ? 'unsigned ' : ''}char"}],
350
+ [Bool , lambda{'_Bool' }],
351
+ [Complex , lambda{'_Complex' }],
352
+ [Imaginary , lambda{'_Imaginary'}]
353
+ ].each do |c, x|
354
+ c.send(:define_method, :to_s) do |*args|
355
+ case args.length
356
+ when 0
357
+ namestr = nil
358
+ when 1
359
+ namestr = args[0]
360
+ namestr = nil if namestr == ''
361
+ else
362
+ raise ArgumentError, "wrong number of args (#{args.length} for 1)"
363
+ end
364
+ str = ''
365
+ const? and str << 'const '
366
+ restrict? and str << 'restrict '
367
+ volatile? and str << 'volatile '
368
+ str << instance_eval(&x) << (namestr ? " #{namestr}" : '')
369
+ end
370
+ end
371
+
372
+ class Enumerator
373
+ def to_s
374
+ if val
375
+ "#{name} = #{val}"
376
+ else
377
+ "#{name}"
378
+ end
379
+ end
380
+ end
381
+
382
+ class Comma
383
+ def to_s
384
+ exprs.join(', ')
385
+ end
386
+ end
387
+
388
+ class Conditional
389
+ def to_s
390
+ strs = [:cond, :then, :else].map do |child|
391
+ val = send(child)
392
+ if val.to_s_precedence < self.to_s_precedence
393
+ "(#{val})"
394
+ else
395
+ "#{val}"
396
+ end
397
+ end
398
+ "#{strs[0]} ? #{strs[1]} : #{strs[2]}"
399
+ end
400
+ end
401
+
402
+ class Call
403
+ def to_s
404
+ argstrs = args.map do |arg|
405
+ if arg.is_a? Comma
406
+ "(#{arg})"
407
+ else
408
+ "#{arg}"
409
+ end
410
+ end
411
+ if expr.to_s_precedence < self.to_s_precedence
412
+ exprstr = "(#{expr})"
413
+ else
414
+ exprstr = "#{expr}"
415
+ end
416
+ "#{exprstr}(#{argstrs.join(', ')})"
417
+ end
418
+ end
419
+
420
+ ### IndirectTypes
421
+ class Pointer
422
+ def to_s name=nil
423
+ str = '*'
424
+ const? and str << 'const '
425
+ restrict? and str << 'restrict '
426
+ volatile? and str << 'volatile '
427
+ str =
428
+ case type
429
+ when Function, Array
430
+ "(#{str}#{name})"
431
+ else
432
+ "#{str}#{name}"
433
+ end
434
+ if type
435
+ type.to_s(str)
436
+ else
437
+ str
438
+ end
439
+ end
440
+ end
441
+ class Array
442
+ def to_s name=nil
443
+ str = "#{name}[#{length}]"
444
+ if type
445
+ type.to_s(str)
446
+ else
447
+ str
448
+ end
449
+ end
450
+ end
451
+ class Function
452
+ def to_s name=nil
453
+ str =
454
+ if params.nil?
455
+ paramstr = ''
456
+ elsif params.empty?
457
+ paramstr = 'void'
458
+ else
459
+ paramstr = params.join(', ')
460
+ end
461
+ var_args? and paramstr << ', ...'
462
+ str = "#{name}(#{paramstr})"
463
+ if type
464
+ type.to_s(str)
465
+ else
466
+ str
467
+ end
468
+ end
469
+ end
470
+ class Parameter
471
+ def to_s
472
+ str = register? ? 'register ' : ''
473
+ str << type.to_s(name)
474
+ end
475
+ end
476
+
477
+ ### Literals
478
+ class StringLiteral
479
+ def to_s
480
+ "\"#{val}\""
481
+ end
482
+ end
483
+ class CharLiteral
484
+ def to_s
485
+ "'#{val}'"
486
+ end
487
+ end
488
+ class CompoundLiteral
489
+ def to_s
490
+ str = ''
491
+ type and
492
+ str << "(#{type}) "
493
+ str << "{\n" << indent(inits.join(",\n")) << "\n}"
494
+ end
495
+ end
496
+ class MemberInit
497
+ def to_s
498
+ str = ''
499
+ if member
500
+ memberstr = member.map do |m|
501
+ if m.is_a? Expression
502
+ "[#{m}]"
503
+ else
504
+ ".#{m}"
505
+ end
506
+ end
507
+ str << member.join(' ') << ' = '
508
+ end
509
+ return str << init.to_s
510
+ end
511
+ end
512
+ class Member
513
+ def to_s
514
+ name.dup
515
+ end
516
+ end
517
+ class IntLiteral
518
+ def to_s
519
+ val.to_s
520
+ end
521
+ end
522
+ class FloatLiteral
523
+ def to_s
524
+ val.to_s
525
+ end
526
+ end
527
+ class Variable
528
+ def to_s
529
+ name.dup
530
+ end
531
+ end
532
+
533
+ ## check we didn't miss any
534
+ CORE_C_NODE_CLASSES.each do |c|
535
+ c.method_defined? :to_s or
536
+ raise "#{c}#to_s not defined"
537
+ end
538
+ end