csquare-cast 0.2.2

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