cast19 0.1.0

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,232 @@
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
+ raise "#{c}#parse not defined" unless c.respond_to? :parse
231
+ end
232
+ end
@@ -0,0 +1,547 @@
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
+ if lval.to_s_precedence < self.to_s_precedence
305
+ lvalstr = "(#{lval})"
306
+ else
307
+ lvalstr = "#{lval}"
308
+ end
309
+ "#{lvalstr} #{op}= #{rvalstr}"
310
+ end
311
+ end
312
+ ## Other Expressions
313
+ class Sizeof
314
+ def to_s
315
+ if expr.is_a? Expression
316
+ if expr.to_s_precedence < self.to_s_precedence
317
+ return "sizeof(#{expr})"
318
+ else
319
+ return "sizeof #{expr}"
320
+ end
321
+ else
322
+ return "sizeof(#{expr})"
323
+ end
324
+ end
325
+ end
326
+ ## DirectTypes
327
+ int_longnesses = ['short ', '', 'long ', 'long long ']
328
+ float_longnesses = ['float', 'double', 'long double']
329
+ [ [Struct, lambda do
330
+ str = 'struct'
331
+ name and str << " #{name}"
332
+ members and str << " {\n" << indent(members.join("\n")) << "\n}"
333
+ str
334
+ end],
335
+ [Union, lambda do
336
+ str = 'union'
337
+ name and str << " #{name}"
338
+ members and str << " {\n" << indent(members.join("\n")) << "\n}"
339
+ str
340
+ end],
341
+ [Enum, lambda do
342
+ str = 'enum'
343
+ name and str << " #{name}"
344
+ members and str << " {\n" << indent(members.join(",\n")) << "\n}"
345
+ str
346
+ end],
347
+ [CustomType, lambda{name.dup }],
348
+ [Void , lambda{'void' }],
349
+ [Int , lambda do
350
+ longness_str = int_longnesses[longness+1].dup
351
+ "#{unsigned? ? 'unsigned ' : ''}#{longness_str}int"
352
+ end],
353
+ [Float , lambda{float_longnesses[longness].dup}],
354
+ [Char , lambda{"#{unsigned? ? 'unsigned ' : ''}char"}],
355
+ [Bool , lambda{'_Bool' }],
356
+ [Complex , lambda{'_Complex' }],
357
+ [Imaginary , lambda{'_Imaginary'}]
358
+ ].each do |c, x|
359
+ c.send(:define_method, :to_s) do |*args|
360
+ case args.length
361
+ when 0
362
+ namestr = nil
363
+ when 1
364
+ namestr = args[0]
365
+ namestr = nil if namestr == ''
366
+ else
367
+ raise ArgumentError, "wrong number of args (#{args.length} for 1)"
368
+ end
369
+ str = ''
370
+ const? and str << 'const '
371
+ restrict? and str << 'restrict '
372
+ volatile? and str << 'volatile '
373
+ str << instance_eval(&x) << (namestr ? " #{namestr}" : '')
374
+ end
375
+ end
376
+
377
+ class Enumerator
378
+ def to_s
379
+ if val
380
+ "#{name} = #{val}"
381
+ else
382
+ "#{name}"
383
+ end
384
+ end
385
+ end
386
+
387
+ class Comma
388
+ def to_s
389
+ exprs.join(', ')
390
+ end
391
+ end
392
+
393
+ class Conditional
394
+ def to_s
395
+ strs = [:cond, :then, :else].map do |child|
396
+ val = send(child)
397
+ if val.to_s_precedence < self.to_s_precedence
398
+ "(#{val})"
399
+ else
400
+ "#{val}"
401
+ end
402
+ end
403
+ "#{strs[0]} ? #{strs[1]} : #{strs[2]}"
404
+ end
405
+ end
406
+
407
+ class Call
408
+ def to_s
409
+ argstrs = args.map do |arg|
410
+ if arg.is_a? Comma
411
+ "(#{arg})"
412
+ else
413
+ "#{arg}"
414
+ end
415
+ end
416
+ if expr.to_s_precedence < self.to_s_precedence
417
+ exprstr = "(#{expr})"
418
+ else
419
+ exprstr = "#{expr}"
420
+ end
421
+ "#{exprstr}(#{argstrs.join(', ')})"
422
+ end
423
+ end
424
+
425
+ ### IndirectTypes
426
+ class Pointer
427
+ def to_s name=nil
428
+ str = '*'
429
+ const? and str << 'const '
430
+ restrict? and str << 'restrict '
431
+ volatile? and str << 'volatile '
432
+ str =
433
+ case type
434
+ when Function, Array
435
+ "(#{str}#{name})"
436
+ else
437
+ "#{str}#{name}"
438
+ end
439
+ if type
440
+ type.to_s(str)
441
+ else
442
+ str
443
+ end
444
+ end
445
+ end
446
+ class Array
447
+ def to_s name=nil
448
+ str = "#{name}[#{length}]"
449
+ if type
450
+ type.to_s(str)
451
+ else
452
+ str
453
+ end
454
+ end
455
+ end
456
+ class Function
457
+ def to_s name=nil
458
+ str =
459
+ if params.nil?
460
+ paramstr = ''
461
+ elsif params.empty?
462
+ paramstr = 'void'
463
+ else
464
+ paramstr = params.join(', ')
465
+ end
466
+ var_args? and paramstr << ', ...'
467
+ str = "#{name}(#{paramstr})"
468
+ if type
469
+ type.to_s(str)
470
+ else
471
+ str
472
+ end
473
+ end
474
+ end
475
+ class Parameter
476
+ def to_s
477
+ str = register? ? 'register ' : ''
478
+ if type
479
+ str << type.to_s(name)
480
+ else
481
+ str << name.to_s
482
+ end
483
+ end
484
+ end
485
+
486
+ ### Literals
487
+ class StringLiteral
488
+ def to_s
489
+ "\"#{val}\""
490
+ end
491
+ end
492
+ class CharLiteral
493
+ def to_s
494
+ "'#{val}'"
495
+ end
496
+ end
497
+ class CompoundLiteral
498
+ def to_s
499
+ str = ''
500
+ type and
501
+ str << "(#{type}) "
502
+ str << "{\n" << indent(member_inits.join(",\n")) << "\n}"
503
+ end
504
+ end
505
+ class MemberInit
506
+ def to_s
507
+ str = ''
508
+ if member
509
+ memberstr = member.map do |m|
510
+ if m.is_a? Expression
511
+ "[#{m}]"
512
+ else
513
+ ".#{m}"
514
+ end
515
+ end
516
+ str << member.join(' ') << ' = '
517
+ end
518
+ return str << init.to_s
519
+ end
520
+ end
521
+ class Member
522
+ def to_s
523
+ name.dup
524
+ end
525
+ end
526
+ class IntLiteral
527
+ def to_s
528
+ val.to_s
529
+ end
530
+ end
531
+ class FloatLiteral
532
+ def to_s
533
+ val.to_s
534
+ end
535
+ end
536
+ class Variable
537
+ def to_s
538
+ name.dup
539
+ end
540
+ end
541
+
542
+ ## check we didn't miss any
543
+ CORE_C_NODE_CLASSES.each do |c|
544
+ c.method_defined? :to_s or
545
+ raise "#{c}#to_s not defined"
546
+ end
547
+ end