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.
- data/.gemtest +0 -0
- data/History.txt +130 -0
- data/Manifest.txt +22 -0
- data/README.rdoc +2200 -0
- data/Rakefile +55 -0
- data/cast.gemspec +26 -0
- data/ext/cast/cast.c +8 -0
- data/ext/cast/cast.h +144 -0
- data/ext/cast/extconf.rb +3 -0
- data/ext/cast/parser.c +287 -0
- data/ext/cast/yylex.c +6610 -0
- data/ext/cast/yylex.re +324 -0
- data/lib/cast.rb +14 -0
- data/lib/cast/c.tab.rb +3414 -0
- data/lib/cast/c.y +901 -0
- data/lib/cast/c_nodes.rb +1096 -0
- data/lib/cast/inspect.rb +57 -0
- data/lib/cast/node.rb +740 -0
- data/lib/cast/node_list.rb +841 -0
- data/lib/cast/parse.rb +255 -0
- data/lib/cast/preprocessor.rb +78 -0
- data/lib/cast/tempfile.rb +186 -0
- data/lib/cast/to_s.rb +555 -0
- data/test/test_helper.rb +192 -0
- metadata +118 -0
data/lib/cast/to_s.rb
ADDED
@@ -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
|