cast19 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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